From cc632e44abdcf4549c35160fdc80e474e357d65f Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 31 Oct 2024 14:38:06 -0600 Subject: [PATCH 01/26] [wizlighting] Initial contribution This binding integrates [WiZ Connected](https://www.wizconnected.com/en-US/) smart devices. This is a successor to the community marketplace version of this binding, most recently maintained by @frejos, bringing it up to date with openHAB guidelines and standards, to be part of the main distribution. User visible changes: * Renamed thing type, channel type, and channel ids to be `lower-case-hyphen` * Removed `wiz-` prefix from thing type ids * Removed `dimming` and `state` channels from `color-bulb` (use `color` channel) * Removed `state` channel from `tunable-bulb` (use `brightness` channel) * Removed `state` channel from `dimmable-bulb` (use `brightness` channel) * Renamed `fan-state` channel to just `state` * Renamed `dimming` channel to `brightness` * Renamed `light-mode` channel to just `mode` * Added `temperature-abs` channel * Fixed INCREASE/DECREASE to `speed` channel changing temperature * Set color temperature to UNDEF when not in color temp mode * Calculate the effective color when in color temp mode Internal changes: * Removed recreation of thing types based on binding version (openHAB core supports update instructions to handle this automatically) * Use PercentType.ZERO, PercentType.HUNDRED, DecimalType.ZERO as appropriate * Splits updates for fan and light apart, to reduce confusion * Remove lots of debugging-style logging * Address several compilation warnings Co-authored-by: Joshua Freeman Co-authored-by: Stefan Fussenegger Co-authored-by: Sara Damiano Signed-off-by: Cody Cutrer --- CODEOWNERS | 1 + bom/openhab-addons/pom.xml | 5 + .../org.openhab.binding.wizlighting/NOTICE | 13 + .../org.openhab.binding.wizlighting/README.md | 138 ++++ .../org.openhab.binding.wizlighting/pom.xml | 17 + .../src/main/feature/feature.xml | 9 + .../internal/WizLightingBindingConstants.java | 139 ++++ .../internal/WizLightingHandlerFactory.java | 76 ++ .../WizLightingDeviceConfiguration.java | 36 + .../WizLightingDiscoveryService.java | 268 +++++++ .../internal/entities/ColorRequestParam.java | 105 +++ .../ColorTemperatureRequestParam.java | 53 ++ .../entities/DimmingRequestParam.java | 55 ++ .../entities/ErrorResponseResult.java | 38 + .../entities/FanStateRequestParam.java | 38 + .../entities/FirstBeatResponseParam.java | 42 + .../wizlighting/internal/entities/Param.java | 26 + .../internal/entities/PulseRequestParam.java | 56 ++ .../entities/RegistrationRequestParam.java | 84 ++ .../internal/entities/SceneRequestParam.java | 46 ++ .../internal/entities/SpeedRequestParam.java | 49 ++ .../internal/entities/StateRequestParam.java | 41 + .../internal/entities/SystemConfigResult.java | 74 ++ .../internal/entities/WizLightingRequest.java | 77 ++ .../entities/WizLightingResponse.java | 149 ++++ .../entities/WizLightingSyncState.java | 159 ++++ .../internal/enums/WizLightingColorMode.java | 47 ++ .../internal/enums/WizLightingLightMode.java | 107 +++ .../internal/enums/WizLightingMethodType.java | 142 ++++ .../internal/enums/WizLightingModuleType.java | 62 ++ .../internal/handler/WizLightingHandler.java | 756 ++++++++++++++++++ .../internal/handler/WizLightingMediator.java | 87 ++ .../handler/WizLightingMediatorImpl.java | 247 ++++++ .../WizLightingUpdateReceiverRunnable.java | 142 ++++ .../internal/utils/NetworkUtils.java | 73 ++ .../internal/utils/ValidationUtils.java | 56 ++ .../internal/utils/WizColorConverter.java | 167 ++++ .../utils/WizLightingPacketConverter.java | 92 +++ .../utils/WizResponseDeserializer.java | 221 +++++ .../src/main/resources/OH-INF/addon/addon.xml | 11 + .../main/resources/OH-INF/config/config.xml | 41 + .../OH-INF/i18n/wizlighting.properties | 72 ++ .../resources/OH-INF/thing/thing-types.xml | 153 ++++ bundles/pom.xml | 1 + 44 files changed, 4271 insertions(+) create mode 100644 bundles/org.openhab.binding.wizlighting/NOTICE create mode 100644 bundles/org.openhab.binding.wizlighting/README.md create mode 100644 bundles/org.openhab.binding.wizlighting/pom.xml create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/config/config.xml create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties create mode 100644 bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml diff --git a/CODEOWNERS b/CODEOWNERS index dd285213ecc2a..e202848ab41eb 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -421,6 +421,7 @@ /bundles/org.openhab.binding.wemo/ @hmerk @jlaur /bundles/org.openhab.binding.wifiled/ @openhab/add-ons-maintainers /bundles/org.openhab.binding.windcentrale/ @marcelrv @wborn +/bundles/org.openhab.binding.wizlighting/ @ccutrer @frejos /bundles/org.openhab.binding.wlanthermo/ @CSchlipp /bundles/org.openhab.binding.wled/ @Skinah /bundles/org.openhab.binding.wolfsmartset/ @BoBiene diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index f2684cc5cd208..cafcb0e4f1c2d 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -2081,6 +2081,11 @@ org.openhab.binding.windcentrale ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.wizlighting + ${project.version} + org.openhab.addons.bundles org.openhab.binding.wlanthermo diff --git a/bundles/org.openhab.binding.wizlighting/NOTICE b/bundles/org.openhab.binding.wizlighting/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* 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 diff --git a/bundles/org.openhab.binding.wizlighting/README.md b/bundles/org.openhab.binding.wizlighting/README.md new file mode 100644 index 0000000000000..a786527fc5582 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/README.md @@ -0,0 +1,138 @@ +![logo](https://www.wizconnected.com/content/dam/wiz/master/logo-wiz-black-navigation.svg) + +This binding integrates [WiZ Connected](https://www.wizconnected.com/en-US/) smart devices. +These inexpensive devices, typically smart bulbs, are available online and in most Home Depot stores. +They come in a variety of bulb shapes and sizes with options of full color with tunable white, tunable white, and dimmable white. +This binding has been tested with various bulbs and switchable plugs. +They are sold under the Philips brand name. +(Wiz is owned by Signify (formerly Philips Lighting).) +*Note* that while both are sold by Philips, WiZ bulbs are *not* part of the Hue ecosystem. + +This binding operates completely within the local network - the discovery, control, and status monitoring is entirely over UDP in the local network. +The binding never attempts to contact the WiZ servers in any way but does not stop them from doing so independently. +It should not interfere in any way with control of the bulbs via the WiZ app or any other service integrated with the WiZ app (ie: Alexa, IFTTT, SmartThings). +Any changes made to the bulb state outside of openHAB should be detected by the binding and vice-versa. +Before using the binding, the bulbs must be set up using the WiZ iOS or Android app. +Local control must also be enabled with-in the WiZ app in the app settings. +(This is the default.) + +## Supported Things +* WiZ Full Color with Tunable White Bulbs +* WiZ Tunable White Bulbs +* WiZ Dimmable single-color bulbs +* Wiz Smart Plugs + +_Note_ This binding was created for and tested on the full color with tunable white bulbs, however, users have reported success with other bulb types and plugs. + +## Discovery +New devices can be discovered by scanning and may also be discovered by background discovery. +All discovered devices will default to 'Full Color' bulbs if unable to automatically detect the specific device type. You may need to create devices manually if desired. + +Devices must first have been set up using the WiZ iOS or Android app. If the binding cannot discover your device, try unplugging it, wait several seconds, and plug it back in. + +## Binding Configuration + +The binding does not require any special configuration. +You can optionally manually set the IP and MAC address of the openHAB instance; if you do not set them, the binding will use the system defaults. + +## Thing Configuration + +To create or configure a device manually you need its IP address and MAC address. +These can be quickly found in the ios or android app by entering the settings for device in question and clicking on the model name. +The refresh interval may also be set; if unset it defaults to 30 seconds. +If you desire instant updates, you may also enable "heart-beat" synchronization with the bulbs. +Heart-beats are not used by default. +When heart-beats are enabled, the binding will continuously re-register with the bulbs to receive sync packets on every state change and on every 5 seconds. +Enabling heart-beats causes the refresh-interval to be ignored. +If heart-beats are not enabled, the channels are only updated when polled at the set interval and thus will be slightly delayed wrt changes made to the bulb state outside of the binding (ie, via the WiZ app). + +**NOTE:** While the bulb's IP address is needed for initial manual configuration, this binding _does not_ require you to use a static IP for each bulb. +After initial discovery or setup, the binding will automatically search for and re-match bulbs with changed IP addresses by MAC address once every hour. + +Thing parameters: + +| Parameter ID | Parameter Type | Mandatory | Description | Default | +|-------------------|----------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------| +| macAddress | text | true | The MAC address of the bulb | | +| ipAddress | text | true | The IP of the bulb | | +| updateInterval | integer | false | Update time interval in seconds to request the status of the bulb. | 60 | +| useHeartBeats | boolean | false | Whether to register for continuous 5s heart-beats | false | +| reconnectInterval | integer | false | Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. | 15 | + +Example Thing: + +``` +Thing wizlighting:bulb:lamp "My Lamp" @ "Living Room" [ macAddress="accf23343cxx", ipAddress="192.168.0.xx" ] +``` + +## Channels + +The Binding supports the following channels: + +| Channel Type ID | Item Type | Description | Access | +|-----------------|--------------------|-------------------------------------------------------|--------| +| color | Color | State, intensity, and color of the LEDs | R/W | +| temperature | Dimmer | Color temperature of the bulb | R/W | +| temperature-abs | Number:Temperature | Color temperature of the bulb in Kelvin | R/W | +| brightness | Dimmer | The brightness of the bulb | R/W | +| state | Switch | Whether the bulb is on or off | R/W | +| light-mode | Number | Preset light mode name to run | R/W | +| speed | Dimmer | Speed of the color changes in dynamic light modes | R/W | +| signal-strength | system | Quality of the bulb's WiFi connection | R | +| last-update | Time | The last time an an update was received from the bulb | R | + +## Light Modes + +The Binding supports the following Light Modes + +| ID | Scene Name | +|----|---------------| +| 1 | Ocean | +| 2 | Romance | +| 3 | Sunset | +| 4 | Party | +| 5 | Fireplace | +| 6 | Cozy White | +| 7 | Forest | +| 8 | Pastel Colors | +| 9 | Wakeup | +| 10 | Bed Time | +| 11 | Warm White | +| 12 | Daylight | +| 13 | Cool White | +| 14 | Night Light | +| 15 | Focus | +| 16 | Relax | +| 17 | True Colors | +| 18 | TV Time | +| 19 | Plant Growth | +| 20 | Spring | +| 21 | Summer | +| 22 | Fall | +| 23 | Deep Dive | +| 24 | Jungle | +| 25 | Mojito | +| 26 | Club | +| 27 | Christmas | +| 28 | Halloween | +| 29 | Candlelight | +| 30 | Golden White | +| 31 | Pulse | +| 32 | Steampunk | + +## Bulb Limitations +- Full-color bulbs operate in either color mode OR tunable white/color temperature mode. +The RGB LED's are NOT used to control temperature - separate warm and cool white LED's are used. +Sending a command on the color channel or the temperature channel will cause the bulb to switch the relevant mode. +- Dimmable bulbs do not dim below 10%. +- The binding attempts to immediately retrieve the actual state from the device after each command is acknowledged, sometimes this means your settings don't 'stick' this is because the device itself did not accept the command or setting. +- Parameters can not be changed while the bulbs are off, sending any commands to change any settings will cause the bulbs to turn on. +- Power on behavior is configured in the app. +- Fade in/out times are configured in the app. +- Sending too many commands to the bulbs too quickly can cause them to stop responding for a period of time. + +## Example item linked to a channel + +``` +Color LivingRoom_Light_Color "Living Room Lamp" (gLivingroom) {channel="wizlighting:color-bulb:accf23343cxx:color"} +``` diff --git a/bundles/org.openhab.binding.wizlighting/pom.xml b/bundles/org.openhab.binding.wizlighting/pom.xml new file mode 100644 index 0000000000000..a049f1b4145e3 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.3.0-SNAPSHOT + + + org.openhab.binding.wizlighting + + openHAB Add-ons :: Bundles :: WiZ Lighting Binding + + diff --git a/bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml b/bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml new file mode 100644 index 0000000000000..334b646b4c816 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.wizlighting/${project.version} + + diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java new file mode 100644 index 0000000000000..06d7f0e80b068 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java @@ -0,0 +1,139 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal; + +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link WizLightingBindingConstants} class defines common constants, which + * are used across the whole binding. + * + * @author Sriram Balakrishnan - Initial contribution + * @author Joshua Freeman - update version + */ +@NonNullByDefault +public class WizLightingBindingConstants { + + /** + * The binding id. + */ + public static final String BINDING_ID = "wizlighting"; + + /** + * List of all Thing Type UIDs. + */ + public static final ThingTypeUID THING_TYPE_COLOR_BULB = new ThingTypeUID(BINDING_ID, "color-bulb"); + public static final ThingTypeUID THING_TYPE_TUNABLE_BULB = new ThingTypeUID(BINDING_ID, "tunable-bulb"); + public static final ThingTypeUID THING_TYPE_DIMMABLE_BULB = new ThingTypeUID(BINDING_ID, "dimmable-bulb"); + public static final ThingTypeUID THING_TYPE_SMART_PLUG = new ThingTypeUID(BINDING_ID, "plug"); + public static final ThingTypeUID THING_TYPE_CEILING_FAN = new ThingTypeUID(BINDING_ID, "ceiling-fan"); + + /** + * The supported thing types. + */ + public static final Set SUPPORTED_THING_TYPES = Stream.of(THING_TYPE_COLOR_BULB, + THING_TYPE_TUNABLE_BULB, THING_TYPE_DIMMABLE_BULB, THING_TYPE_SMART_PLUG, THING_TYPE_CEILING_FAN) + .collect(Collectors.toSet()); + + /** + * List of all Channel ids + */ + public static final String CHANNEL_BRIGHTNESS = "brightness"; + public static final String CHANNEL_COLOR = "color"; + public static final String CHANNEL_LAST_UPDATE = "last-update"; + public static final String CHANNEL_MODE = "mode"; + public static final String CHANNEL_REVERSE = "reverse"; + public static final String CHANNEL_RSSI = "signal-strength"; + public static final String CHANNEL_SPEED = "speed"; + public static final String CHANNEL_STATE = "state"; + public static final String CHANNEL_TEMPERATURE = "temperature"; + public static final String CHANNEL_TEMPERATURE_ABS = "temperature-abs"; + + // -------------- Configuration arguments ---------------- + /** + * Mac address configuration argument key. + */ + public static final String CONFIG_MAC_ADDRESS = "bulbMacAddress"; + public static final String MISSING_INVALID_MAC_ADDRESS = "bulbMacAddress"; + + /** + * Host address configuration argument key. + */ + public static final String CONFIG_IP_ADDRESS = "bulbIpAddress"; + public static final String MISSING_INVALID_IP_ADDRESS = "bulbIpAddress"; + + /** + * Wifi socket update interval configuration argument key. + */ + public static final String CONFIG_UPDATE_INTERVAL = "updateInterval"; + public static final long DEFAULT_REFRESH_INTERVAL_SEC = 60; + + /** + * Wifi socket update interval configuration argument key. + */ + public static final String CONFIG_RECONNECT_INTERVAL = "reconnectInterval"; + public static final long DEFAULT_RECONNECT_INTERVAL_MIN = 15; + + // -------------- Default values ---------------- + + /** + * The number of refresh intervals without a response before a bulb is marked + * offline + */ + public static final int MARK_OFFLINE_AFTER_SEC = 5 * 60; + + /** + * Default Wifi socket default UDP port. + */ + public static final int DEFAULT_BULB_UDP_PORT = 38899; + + /** + * Default listener socket default UDP port. + */ + public static final int DEFAULT_LISTENER_UDP_PORT = 38900; + + /** + * How long before active discovery times out. + */ + public static final int DISCOVERY_TIMEOUT_SECONDS = 2; + + // -------------- Constants Used ---------------- + + /** + * The color temperature range of the WiZ bulbs + */ + public static final int MIN_COLOR_TEMPERATURE = 2200; + public static final int MAX_COLOR_TEMPERATURE = 6500; + public static final int COLOR_TEMPERATURE_RANGE = MAX_COLOR_TEMPERATURE - MIN_COLOR_TEMPERATURE; + + // -------------- Bulb Properties ---------------- + + public static final String PROPERTY_BINDING_VERSION = "bindingVersion"; + public static final String PROPERTY_IP_ADDRESS = "ipAddress"; + + public static final String PROPERTY_HOME_ID = "homeId"; + public static final String PROPERTY_ROOM_ID = "roomId"; + public static final String PROPERTY_HOME_LOCK = "homeLock"; + public static final String PROPERTY_PAIRING_LOCK = "pairingLock"; + public static final String PROPERTY_TYPE_ID = "typeId"; + public static final String PROPERTY_MODULE_NAME = "moduleName"; + public static final String PROPERTY_GROUP_ID = "groupId"; + + public static final String EXPECTED_MODULE_NAME = "ESP01_SHRGB1C_31"; + public static final String LAST_KNOWN_FIRMWARE_VERSION = "1.18.0"; +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java new file mode 100644 index 0000000000000..15287cae816d1 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java @@ -0,0 +1,76 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.handler.WizLightingHandler; +import org.openhab.binding.wizlighting.internal.handler.WizLightingMediator; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link WizLightingHandlerFactory} is responsible for creating things and + * thing handlers. + * + * @author Sriram Balakrishnan - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.wizlighting", service = ThingHandlerFactory.class) +public class WizLightingHandlerFactory extends BaseThingHandlerFactory { + private final Logger logger = LoggerFactory.getLogger(WizLightingHandlerFactory.class); + + private final WizLightingMediator mediator; + + @Activate + public WizLightingHandlerFactory(@Reference WizLightingMediator mediator) { + this.mediator = mediator; + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(final Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (supportsThingType(thing.getThingTypeUID())) { + WizLightingHandler handler; + + handler = new WizLightingHandler(thing, this.mediator.getRegistrationParams()); + + mediator.registerThingAndWizBulbHandler(thing, handler); + return handler; + } else { + logger.warn("Thing type {} not supported.", thingTypeUID); + } + return null; + } + + @Override + public void unregisterHandler(final Thing thing) { + mediator.unregisterWizBulbHandlerByThing(thing); + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java new file mode 100644 index 0000000000000..84e4024addebe --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java @@ -0,0 +1,36 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.config; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link BondHomeConfiguration} class contains fields mapping thing + * configuration parameters. + * + * @author Sara Geleskie Damiano - Initial contribution + */ +@NonNullByDefault +public class WizLightingDeviceConfiguration { + + /** + * Configuration for a Bond Bridge or Device + */ + public String bulbMacAddress = MISSING_INVALID_MAC_ADDRESS; + public String bulbIpAddress = MISSING_INVALID_IP_ADDRESS; + public long updateInterval = DEFAULT_REFRESH_INTERVAL_SEC; + public boolean useHeartBeats = false; // true: register to get 5s heart-beats + public long reconnectInterval = DEFAULT_RECONNECT_INTERVAL_MIN; +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java new file mode 100644 index 0000000000000..8a7be7239efd6 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java @@ -0,0 +1,268 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.discovery; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketTimeoutException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +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.binding.wizlighting.internal.entities.SystemConfigResult; +import org.openhab.binding.wizlighting.internal.entities.WizLightingRequest; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; +import org.openhab.binding.wizlighting.internal.handler.WizLightingMediator; +import org.openhab.binding.wizlighting.internal.utils.WizLightingPacketConverter; +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.config.discovery.DiscoveryService; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.ThingUID; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is the {@link DiscoveryService} for the Wizlighting Items. + * + * @author Sriram Balakrishnan - Initial contribution + * @author Joshua Freeman - use configured Broadcast address instead of guessing, discovery of plugs + * + */ +@Component(configurationPid = "discovery.wizlighting", service = DiscoveryService.class, immediate = true) +@NonNullByDefault +public class WizLightingDiscoveryService extends AbstractDiscoveryService { + + private final Logger logger = LoggerFactory.getLogger(WizLightingDiscoveryService.class); + + private final WizLightingMediator mediator; + + private final WizLightingPacketConverter converter = new WizLightingPacketConverter(); + + private @Nullable ScheduledFuture bulbBackgroudDiscovery; + + /** + * Constructor of the discovery service. + * + * @throws IllegalArgumentException if the timeout < 0 + */ + @Activate + public WizLightingDiscoveryService( + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC) WizLightingMediator mediator) + throws IllegalArgumentException { + super(SUPPORTED_THING_TYPES, DISCOVERY_TIMEOUT_SECONDS, true); + this.mediator = mediator; + mediator.setDiscoveryService(this); + } + + @Override + public Set getSupportedThingTypes() { + return SUPPORTED_THING_TYPES; + } + + /** + * This method is called when {@link AbstractDiscoveryService#setBackgroundDiscoveryEnabled(boolean)} + * is called with true as parameter and when the component is being activated + * (see {@link AbstractDiscoveryService#activate()}. + * + * This will also serve to "re-discover" any bulbs that have changed to a new IP address. + */ + @Override + protected void startBackgroundDiscovery() { + ScheduledFuture backgroundDiscovery = bulbBackgroudDiscovery; + if (backgroundDiscovery == null || backgroundDiscovery.isCancelled()) { + bulbBackgroudDiscovery = scheduler.scheduleWithFixedDelay(this::startScan, 1, 60, TimeUnit.MINUTES); + } + } + + @Override + protected void stopBackgroundDiscovery() { + ScheduledFuture backgroundDiscovery = bulbBackgroudDiscovery; + if (backgroundDiscovery != null && !backgroundDiscovery.isCancelled()) { + backgroundDiscovery.cancel(true); + bulbBackgroudDiscovery = null; + } + } + + @Override + protected void startScan() { + DatagramSocket dsocket = null; + try { + String broadcastIp = this.mediator.getNetworkAddressService().getConfiguredBroadcastAddress(); + if (broadcastIp != null) { + InetAddress address = InetAddress.getByName(broadcastIp); + WizLightingRequest request = new WizLightingRequest(WizLightingMethodType.Registration, + this.mediator.getRegistrationParams()); + request.setId(0); + + byte[] message = this.converter.transformToByteMessage(request); + + // Initialize a datagram packet with data and address + DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_BULB_UDP_PORT); + + // Create a datagram socket, send the packet through it, close it. + // For discovery we will "fire and forget" and let the mediator take care of the + // responses + dsocket = new DatagramSocket(); + dsocket.send(packet); + logger.debug("Broadcast packet to address: {} and port {}", address, DEFAULT_BULB_UDP_PORT); + } else { + logger.warn("No broadcast address was configured or discovered! No broadcast sent."); + } + } catch (IOException exception) { + logger.debug("Something wrong happened when broadcasting the packet to port {}... msg: {}", + DEFAULT_BULB_UDP_PORT, exception.getMessage()); + } finally { + if (dsocket != null) { + dsocket.close(); + } + } + } + + /** + * Method called by mediator, after receiving a packet from an unknown WiZ bulb + * + * @param bulbMacAddress the mac address from the device. + * @param bulbIpAddress the host address from the device. + */ + public void discoveredLight(final String lightMacAddress, final String lightIpAddress) { + Map properties = new HashMap<>(2); + properties.put(CONFIG_MAC_ADDRESS, lightMacAddress); + properties.put(CONFIG_IP_ADDRESS, lightIpAddress); + logger.trace("New bulb discovered at {} with MAC {}. Requesting configuration info from the bulb.", + lightIpAddress, lightMacAddress); + + // Assume it is a full color bulb, unless we get confirmation otherwise. + // This will ensure the maximum number of channels will be created so there's no + // missing functionality. + // There's nothing a simple dimmable bulb can do that a full color bulb can't. + // It's easy for a user to ignore or not link anything to a non-working channel, + // but impossible to add a new channel if it's wanted. + // The bulbs will merely ignore or return an error for specific commands they + // cannot carry-out (ie, setting color on a non-color bulb) and continue to + // function as they were before the bad command. + ThingTypeUID thisBulbType = THING_TYPE_COLOR_BULB; + String thisBulbLabel = "WiZ Full Color Bulb at " + lightIpAddress; + ThingUID newThingId = new ThingUID(thisBulbType, lightMacAddress); + + WizLightingResponse configResponse = getDiscoveredBulbConfig(lightIpAddress); + if (configResponse != null) { + SystemConfigResult discoveredBulbConfig = configResponse.getSystemConfigResults(); + if (discoveredBulbConfig != null) { + String discoveredModel = discoveredBulbConfig.moduleName.toUpperCase(); + logger.trace("Returned model from discovered bulb at {}: {}", lightIpAddress, discoveredModel); + + // “moduleName”:“ESP10_SOCKET_06” confirmed example module name for Wiz Smart Plug + // Check for "SOCKET" this seems safe based on other naming conventions observed + if (discoveredModel.contains("SOCKET")) { + thisBulbType = THING_TYPE_SMART_PLUG; + thisBulbLabel = "WiZ Smart Plug at " + lightIpAddress; + newThingId = new ThingUID(thisBulbType, lightMacAddress); + logger.trace("New device appears to be a smart plug and will be given the UUID: {}", newThingId); + + // We'll try to key off "TW" for tunable white + } else if (discoveredModel.contains("TW")) { + thisBulbType = THING_TYPE_TUNABLE_BULB; + thisBulbLabel = "WiZ Tunable White Bulb at " + lightIpAddress; + newThingId = new ThingUID(thisBulbType, lightMacAddress); + logger.trace("New bulb appears to be a tunable white bulb and will be given the UUID: {}", + newThingId); + + // Check for "FANDIMS" as in confirmed example ESP03_FANDIMS_31 for Faro Barcelona Smart Fan + } else if (discoveredModel.contains("FANDIMS")) { + thisBulbType = THING_TYPE_CEILING_FAN; + thisBulbLabel = "WiZ Smart Fan at " + lightIpAddress; + newThingId = new ThingUID(thisBulbType, lightMacAddress); + logger.trace("New device appears to be a smart fan and will be given the UUID: {}", newThingId); + + // We key off "RGB" for color bulbs + } else if (!discoveredModel.contains("RGB")) { + thisBulbType = THING_TYPE_DIMMABLE_BULB; + thisBulbLabel = "WiZ Dimmable White Bulb at " + lightIpAddress; + newThingId = new ThingUID(thisBulbType, lightMacAddress); + logger.trace( + "New bulb appears not to be either tunable white bulb or full color and will be called dimmable only and given the UUID: {}", + newThingId); + } + + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(newThingId).withProperties(properties) + .withLabel(thisBulbLabel).withRepresentationProperty(CONFIG_MAC_ADDRESS).build(); + + this.thingDiscovered(discoveryResult); + } + } else { + logger.trace( + "Couldn't get or couldn't parse configuration information from discovered bulb. Discovery result will not be created."); + } + } + + private synchronized @Nullable WizLightingResponse getDiscoveredBulbConfig(final String lightIpAddress) { + DatagramSocket dsocket = null; + try { + WizLightingRequest request = new WizLightingRequest(WizLightingMethodType.GetSystemConfig, null); + request.setId(1); + + byte[] message = this.converter.transformToByteMessage(request); + + // Initialize a datagram packet with data and address + InetAddress address = InetAddress.getByName(lightIpAddress); + DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_BULB_UDP_PORT); + + // Create a datagram socket, send the packet through it, close it. + dsocket = new DatagramSocket(); + dsocket.send(packet); + logger.debug("Sent packet to address: {} and port {}", address, DEFAULT_BULB_UDP_PORT); + + byte[] responseMessage = new byte[1024]; + packet = new DatagramPacket(responseMessage, responseMessage.length); + dsocket.receive(packet); + + return converter.transformResponsePacket(packet); + } catch (SocketTimeoutException e) { + logger.trace("Socket timeout after sending command; no response from {} within 500ms", lightIpAddress); + } catch (IOException exception) { + logger.debug("Something wrong happened when sending the packet to address: {} and port {}... msg: {}", + lightIpAddress, DEFAULT_BULB_UDP_PORT, exception.getMessage()); + } finally { + if (dsocket != null) { + dsocket.close(); + } + } + return null; + } + + // SETTERS AND GETTERS + /** + * Gets the {@link WizLightingMediator} of this binding. + * + * @return {@link WizLightingMediator}. + */ + public WizLightingMediator getMediator() { + return this.mediator; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java new file mode 100644 index 0000000000000..bed1c7ead3fe4 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java @@ -0,0 +1,105 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.wizlighting.internal.utils.WizColorConverter; +import org.openhab.core.library.types.HSBType; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Color Request Param + * + * Outgoing JSON should look like this: + * + * {"id": 24, "method": "setPilot", "params": {"r": 0, "g": 230, "b": 80, "w": + * 130, "c": 0, "dimming": 12}} + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class ColorRequestParam extends DimmingRequestParam { + @Expose(serialize = true, deserialize = true) + private int r; // red 0-255 + @Expose(serialize = true, deserialize = true) + private int g; // green 0-255 + @Expose(serialize = true, deserialize = true) + private int b; // blue 0-255 + @Expose(serialize = true, deserialize = true) + private int w; // warm white LED's 0-255 + @Expose(serialize = true, deserialize = true) + private int c; // cool white LED's 0-255 + @Expose(serialize = false, deserialize = false) + private WizColorConverter colorConverter = new WizColorConverter(); + + public ColorRequestParam(int r, int g, int b, int w, int c, int dimming) { + super(dimming); + this.r = r; + this.g = g; + this.b = b; + this.w = w; + this.c = c; + } + + public ColorRequestParam(HSBType hsb) { + super(hsb.getBrightness().intValue()); + int rgbw[] = colorConverter.hsbToRgbw(hsb); + this.r = rgbw[0]; + this.g = rgbw[1]; + this.b = rgbw[2]; + this.w = rgbw[3]; + this.c = 0; + } + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + public int getG() { + return g; + } + + public void setG(int g) { + this.g = g; + } + + public int getR() { + return r; + } + + public void setR(int r) { + this.r = r; + } + + public int getW() { + return w; + } + + public void setW(int w) { + this.w = w; + } + + public int getC() { + return c; + } + + public void setC(int c) { + this.c = c; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java new file mode 100644 index 0000000000000..bcb0fd6e446ea --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java @@ -0,0 +1,53 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.library.types.PercentType; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Color Request Param + * + * The outgoing JSON should look like this: + * + * {"id": 24, "method": "setPilot", "params": {"temp": 3000}} + * + * @author Alexander Seeliger - Initial contribution + * + */ +@NonNullByDefault +public class ColorTemperatureRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private int temp; + + public ColorTemperatureRequestParam(int temp) { + this.temp = temp; + } + + public ColorTemperatureRequestParam(PercentType colorPercent) { + // NOTE: 0% is cold (highest K) and 100% is warm (lowest K) + temp = MAX_COLOR_TEMPERATURE - Math.round((COLOR_TEMPERATURE_RANGE * colorPercent.floatValue()) / 100); + } + + public int getColorTemperature() { + return temp; + } + + public void setColorTemperature(int temp) { + this.temp = temp; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java new file mode 100644 index 0000000000000..52fb07ce9d1e4 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java @@ -0,0 +1,55 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Dimming Request Param + * + * The outgoing JSON should look like this: + * + * {"id": 24, "method": "setPilot", "params": {"dimming": 10}} + * + * NOTE: Dimming cannot be set below 10%. Sending a command with a value of less + * than 10 will cause the bulb to reply with an error. + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class DimmingRequestParam extends StateRequestParam { + @Expose(serialize = true, deserialize = true) + private int dimming; + + public DimmingRequestParam(int dimming) { + super(true); + setDimming(dimming); + } + + public int getDimming() { + return dimming; + } + + public void setDimming(int dimming) { + if (dimming <= 10) { + dimming = 10; + } + if (dimming >= 100) { + dimming = 100; + } + this.dimming = dimming; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java new file mode 100644 index 0000000000000..d186dd5cf29a5 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java @@ -0,0 +1,38 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents the "result" of one WiZ Lighting Response "results" are + * returned from registration, pulse, setPilot, and (presumably) setSysConfig + * commands + * + * Incoming JSON might look like this: + * + * {"env":"pro","error":{"code":-32700,"message":"Parse error"}} + * + * @author Sara Geleskie - Initial contribution + * + */ +@NonNullByDefault +public class ErrorResponseResult { + @Expose(serialize = true, deserialize = true) + public int code; + @Expose(serialize = true, deserialize = true) + public @Nullable String message; +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java new file mode 100644 index 0000000000000..77e168cac4874 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java @@ -0,0 +1,38 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Fan State Request Param + */ +@NonNullByDefault +public class FanStateRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private int fanState; // true = 1, false = 0 + + public FanStateRequestParam(int fanState) { + this.fanState = fanState; + } + + public int getFanState() { + return fanState; + } + + public void setFanState(int fanState) { + this.fanState = fanState; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java new file mode 100644 index 0000000000000..be05f4e7a7067 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java @@ -0,0 +1,42 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents the "params" returned in a "firstBeat" + * + * The incoming JSON looks like this: + * + * {"method": "firstBeat", "id": 0, "env": "pro", "params": {"mac": "theBulbMacAddress", + * "homeId": xxxxxx, "fwVersion": "1.15.2"}} + * + * @author Sara Geleskie Damiano - Initial contribution + */ +@NonNullByDefault +public class FirstBeatResponseParam { + // The MAC address the response is coming from + @Expose(serialize = true, deserialize = true) + public String mac = MISSING_INVALID_MAC_ADDRESS; + // Home ID of the bulb + @Expose(serialize = false, deserialize = true) + public int homeId; + // Firmware version of the bulb + @Expose(serialize = true, deserialize = true) + public String fwVersion = LAST_KNOWN_FIRMWARE_VERSION; +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java new file mode 100644 index 0000000000000..1398cd075492b --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java @@ -0,0 +1,26 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * This POJO represents an abstract Request Param + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public interface Param { + +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java new file mode 100644 index 0000000000000..ff1ffac1eed10 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java @@ -0,0 +1,56 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Pulse Request Param + * + * The outgoing JSON should look like this: + * + * {"id": 22, "method": "pulse", "params": {"delta": 30, "duration": 900}} + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ +@NonNullByDefault +public class PulseRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private int delta; + @Expose(serialize = true, deserialize = true) + private int duration; + + public PulseRequestParam(int delta, int duration) { + this.delta = delta; + this.duration = duration; + } + + public int getDelta() { + return delta; + } + + public void setDelta(int delta) { + this.delta = delta; + } + + public int getDuration() { + return duration; + } + + public void setDuration(int duration) { + this.delta = duration; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java new file mode 100644 index 0000000000000..03e167957f33d --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java @@ -0,0 +1,84 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Registration request param + * + * The outgoing JSON should look like this: + * + * {"id": 22, "method": "registration", "params": {"phoneIp": "10.0.0.xx", + * "register": true, "homeId": xxx, "phoneMac": "xxx"}} + * + * NOTE: This can be sent directly to a single bulb or as a UDP broadcast. When + * sent as a broadcast, all bulbs in the network should respond. + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class RegistrationRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private String phoneIp; + @Expose(serialize = true, deserialize = true) + private boolean register; + // NOTE: We are NOT exposing the Home id for serialization because it's not + // necessary and it's a PITA to find it + @Expose(serialize = false, deserialize = true) + private int homeId; + @Expose(serialize = true, deserialize = true) + private String phoneMac; + + public RegistrationRequestParam(String phoneIp, boolean register, int homeId, String phoneMac) { + this.phoneIp = phoneIp; + this.register = register; + this.homeId = homeId; + this.phoneMac = phoneMac; + } + + public String getPhoneIp() { + return phoneIp; + } + + public void setPhoneIp(String phoneIp) { + this.phoneIp = phoneIp; + } + + public boolean getRegister() { + return register; + } + + public void setRegister(boolean register) { + this.register = register; + } + + public int getHomeId() { + return homeId; + } + + public void setHomeId(int homeId) { + this.homeId = homeId; + } + + public String getPhoneMac() { + return phoneMac; + } + + public void setPhoneMac(String phoneMac) { + this.phoneMac = phoneMac; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java new file mode 100644 index 0000000000000..3244509b2d3cb --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java @@ -0,0 +1,46 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents one Scene Request Param + * + * The outgoing JSON should look like this: + * + * {"id": 22, "method": "setPilot", "params": {"sceneId": 3}} * + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class SceneRequestParam extends StateRequestParam { + @Expose(serialize = true, deserialize = true) + private int sceneId; + + public SceneRequestParam(int sceneId) { + super(true); + this.sceneId = sceneId; + } + + public int getSceneId() { + return sceneId; + } + + public void setSceneId(int sceneId) { + this.sceneId = sceneId; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java new file mode 100644 index 0000000000000..0eecacca33b8b --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java @@ -0,0 +1,49 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Speed Request Param + * + * The outgoing JSON should look like this: + * + * {"id": 23, "method": "setPilot", "params": {"sceneId":3,"speed": 20}} + * + * NOTE: A sceneId MUST also be specified in the request or the bulb will reply + * with an error. + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class SpeedRequestParam extends SceneRequestParam { + @Expose(serialize = true, deserialize = true) + private int speed; + + public SpeedRequestParam(int sceneId, int speed) { + super(sceneId); + this.speed = speed; + } + + public int getSpeed() { + return speed; + } + + public void setSpeed(int speed) { + this.speed = speed; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java new file mode 100644 index 0000000000000..e91d4b3fda457 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java @@ -0,0 +1,41 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents State Request Param + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class StateRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private boolean state; // true = ON, false = OFF + + public StateRequestParam(boolean state) { + this.state = state; + } + + public boolean getState() { + return state; + } + + public void setState(boolean state) { + this.state = state; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java new file mode 100644 index 0000000000000..c50e7787b9498 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java @@ -0,0 +1,74 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents the "result" of one request for a bulb's system + * configuration I assume the same packet could be used as the param of a + * 'setSystemConfig' request, but I'm not willing to risk ruining my bulbs by + * trying it. + * + * The incoming JSON looks like this: + * + * {"method": "getSystemConfig", "id": 22, "env": "pro", "result": {"mac": + * "theBulbMacAddress", "homeId": xxxxxx, "roomId": xxxxxx, "homeLock": false, + * "pairingLock": false, "typeId": 0, "moduleName": "ESP01_SHRGB1C_31", + * "fwVersion": "1.15.2", "groupId": 0, "drvConf":[33,1]}} + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ +@NonNullByDefault +public class SystemConfigResult { + // The MAC address the response is coming from + @Expose(serialize = true, deserialize = true) + public String mac = MISSING_INVALID_MAC_ADDRESS; + // Home ID of the bulb + @Expose(serialize = true, deserialize = true) + public int homeId; + // The ID of room the bulb is assigned to + @Expose(serialize = true, deserialize = true) + public int roomId; + // Not sure what the home lock is + @Expose(serialize = true, deserialize = true) + public boolean homeLock; + // Also not sure about the pairing lock + @Expose(serialize = true, deserialize = true) + public boolean pairingLock; + // Obviously a type ID + // The value is 0 for both BR30 and A19 full color bulbs + @Expose(serialize = true, deserialize = true) + public int typeId; + // The module name + // The value is "ESP01_SHRGB1C_31" for both BR30 and A19 full color bulbs + @Expose(serialize = true, deserialize = true) + public String moduleName = EXPECTED_MODULE_NAME; + // Firmware version of the bulb + @Expose(serialize = true, deserialize = true) + public String fwVersion = LAST_KNOWN_FIRMWARE_VERSION; + // The ID of group the bulb is assigned to + // I don't know how to group bulbs, all of mine return 0 + @Expose(serialize = true, deserialize = true) + public int groupId; + // Not sure what the numbers mean + // For a full color A19 I get [33,1] + // For a full coloer BR30 I get [37,1] + @Expose(serialize = true, deserialize = true) + public int[] drvConf = {}; +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java new file mode 100644 index 0000000000000..97ecc13a0b2c0 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java @@ -0,0 +1,77 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents one WiZ Lighting UDP Request. + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class WizLightingRequest { + @Expose(serialize = true, deserialize = true) + private int id; + + @Expose(serialize = true, deserialize = true) + private WizLightingMethodType method; + + @Expose(serialize = false, deserialize = false) + private String methodName; + + @Expose(serialize = true, deserialize = false) + private @Nullable Param params; + + /** + * Default constructor. + * + * @param type the {@link WizLightingMethodType} + * @param params {@link Param} + */ + public WizLightingRequest(final WizLightingMethodType method, final @Nullable Param params) { + this.method = method; + this.methodName = method.getMethodName(); + this.params = params; + } + + public @Nullable Param getParams() { + return this.params; + } + + public void setParams(final Param params) { + this.params = params; + } + + public WizLightingMethodType getMethod() { + return this.method; + } + + public void setMethod(final WizLightingMethodType method) { + this.method = method; + this.methodName = method.getMethodName(); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java new file mode 100644 index 0000000000000..16fad513e011e --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java @@ -0,0 +1,149 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents one WiZ Lighting Response + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class WizLightingResponse { + + // The IP address we're coming from + @Expose(serialize = false, deserialize = true) + private String wizResponseIpAddress = MISSING_INVALID_IP_ADDRESS; + + // Increasing numeric value. + // Bulb doesn't seem to care if it receives the same id multiple time + // or commands with lower numbers after higher ones. + @Expose(serialize = true, deserialize = true) + private int id; + // Not sure what env is - value always seems to be "pro" + @Expose(serialize = true, deserialize = true) + private @Nullable String env; + + // An error response + @Expose(serialize = true, deserialize = true) + private @Nullable ErrorResponseResult methodError; + + // The method being used - see the enum for details + // We're setting this to "unknown" + @Expose(serialize = true, deserialize = true) + private WizLightingMethodType method = WizLightingMethodType.UnknownMethod; + + // The MAC address the response is coming from + @Expose(serialize = true, deserialize = true) + private String mac = MISSING_INVALID_MAC_ADDRESS; + + // Whether or not a command succeeded (if the response is from a command) + @Expose(serialize = true, deserialize = true) + private boolean success = false; + + // The system configuration result, if present + @Expose(serialize = true, deserialize = true) + private @Nullable SystemConfigResult configResult; + + // The parameters or result of a command/response + // A "result" is generally returned when solicited using a set/get method and a + // "params" is retuned with an unsolicited sync/heartbeat. The result returned + // from a get method is generally identical to the params returned in the + // heartbeat. + @Expose(serialize = true, deserialize = true) + private @Nullable WizLightingSyncState params; + + /** + * Setters and Getters + */ + + public @Nullable SystemConfigResult getSystemConfigResults() { + return this.configResult; + } + + public void setSystemConfigResult(final SystemConfigResult configResult) { + this.configResult = configResult; + } + + public boolean getResultSuccess() { + return this.success; + } + + public void setResultSucess(final boolean success) { + this.success = success; + } + + public @Nullable WizLightingSyncState getSyncState() { + return this.params; + } + + public void setSyncParams(final WizLightingSyncState params) { + this.params = params; + } + + public String getWizResponseMacAddress() { + return this.mac; + } + + public void setWizResponseMacAddress(final String wizResponseMacAddress) { + this.mac = wizResponseMacAddress; + } + + public String getWizResponseIpAddress() { + return this.wizResponseIpAddress; + } + + public void setWizResponseIpAddress(final String wizResponseIpAddress) { + this.wizResponseIpAddress = wizResponseIpAddress; + } + + public int getId() { + return id; + } + + public void setId(final int id) { + this.id = id; + } + + public @Nullable WizLightingMethodType getMethod() { + return method; + } + + public void setMethod(final WizLightingMethodType method) { + this.method = method; + } + + public @Nullable String getEnv() { + return env; + } + + public void setEnv(final String env) { + this.env = env; + } + + public @Nullable ErrorResponseResult getError() { + return methodError; + } + + public void setError(ErrorResponseResult error) { + this.methodError = error; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java new file mode 100644 index 0000000000000..b4ebf4b1d32b1 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java @@ -0,0 +1,159 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.entities; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.wizlighting.internal.enums.WizLightingColorMode; +import org.openhab.binding.wizlighting.internal.utils.WizColorConverter; +import org.openhab.core.library.types.HSBType; +import org.openhab.core.library.types.PercentType; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents the "params" of the current state of a WiZ bulb. + * These are retruned as the "params" in getPilot, sync, and heartbeat packets + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class WizLightingSyncState { + // The MAC address the response is coming from + @Expose(serialize = true, deserialize = true) + public String mac = MISSING_INVALID_MAC_ADDRESS; + + // The current color mode of the bulb + // We will assume by default that it's a single color bulb + @Expose(serialize = false, deserialize = false) + public WizLightingColorMode colorMode = WizLightingColorMode.SingleColorMode; + @Expose(serialize = false, deserialize = false) + private WizColorConverter colorConverter = new WizColorConverter(); + + /* + * Extra Information only in 'hb' params + */ + // Not sure exactly what this means, seems to be a boolean + // I believe the bulb communicates with the WiZ servers via MQTT + @Expose(serialize = true, deserialize = true) + public int mqttCd; + + /* + * Bulb state information - not all fields are populated + */ + + // The bulb's WiFi signal strength + @Expose(serialize = true, deserialize = true) + public int rssi; + // The overall state of the bulb - on/off + @Expose(serialize = true, deserialize = true) + public boolean state; + // The numeric identifier for a preset lighting mode + @Expose(serialize = true, deserialize = true) + public int sceneId; + // Unknown - not seen by SRGD + @Expose(serialize = true, deserialize = true) + public boolean play; + // The speed of color changes in dynamic lighting modes + @Expose(serialize = true, deserialize = true) + public int speed; + // Strength of the red channel (0-255) + @Expose(serialize = true, deserialize = true) + public int r; + // Strength of the green channel (0-255) + @Expose(serialize = true, deserialize = true) + public int g; + // Strength of the blue channel (0-255) + @Expose(serialize = true, deserialize = true) + public int b; + // Intensity of the cool white channel (0-255) + @Expose(serialize = true, deserialize = true) + public int c; + // Intensity of the warm white channel (0-255) + @Expose(serialize = true, deserialize = true) + public int w; + // Dimming percent (10-100) + @Expose(serialize = true, deserialize = true) + public int dimming; + // Color temperature - sent in place of r/g/b/c/w + // If temperatures are sent, color LED's are not in use + @Expose(serialize = true, deserialize = true) + public int temp; + // Indicates if the light mode is applied following a pre-set "rhythm" + @Expose(serialize = true, deserialize = true) + public int schdPsetId; + + @Expose(serialize = true, deserialize = true) + public int fanState; + @Expose(serialize = true, deserialize = true) + public int fanSpeed; + @Expose(serialize = true, deserialize = true) + public int fanMode; + @Expose(serialize = true, deserialize = true) + public int fanRevrs; + + public WizLightingColorMode getColorMode() { + if (r != 0 || g != 0 || b != 0) { + return WizLightingColorMode.RGBMode; + } else if (temp != 0) { + return WizLightingColorMode.CTMode; + } else { + return WizLightingColorMode.SingleColorMode; + } + } + + public HSBType getHSBColor() { + if (getColorMode() == WizLightingColorMode.RGBMode) { + HSBType newColor = colorConverter.rgbwDimmingToHSB(r, g, b, w, dimming); + // NOTE: The WiZ bulbs do not use the cool white LED's in full color mode. + return newColor; + } else { + // If a rgb color isn't returned, simply call it simply white. + // Do not attempt any conversions given a color temperature. + return HSBType.WHITE; + } + } + + public void setHSBColor(HSBType hsb) { + this.dimming = hsb.getBrightness().intValue(); + int rgbw[] = colorConverter.hsbToRgbw(hsb); + this.r = rgbw[0]; + this.g = rgbw[1]; + this.b = rgbw[2]; + this.w = rgbw[3]; + this.c = 0; + } + + public int getTemperature() { + return temp; + } + + public PercentType getTemperaturePercent() { + return new PercentType((temp - MIN_COLOR_TEMPERATURE) / COLOR_TEMPERATURE_RANGE * 100); + } + + public void setTemperaturePercent(PercentType colorPercent) { + // NOTE: 0% is cold (highest K) and 100% is warm (lowest K) + this.temp = MAX_COLOR_TEMPERATURE - Math.round((COLOR_TEMPERATURE_RANGE * colorPercent.floatValue()) / 100); + } + + public void setTemperature(int temp) { + this.temp = temp; + } + + public int getDimming() { + return this.dimming; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java new file mode 100644 index 0000000000000..ee6816b079c26 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java @@ -0,0 +1,47 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.enums; + +/** + * This enum represents the possible color modes for WiZ bulbs. + * The bulbs come in three types - full color with tunable white, + * tunable white, and dimmable with set white. The full color and + * tunable white bulbs operate EITHER in color mode OR in tunable + * white mode. + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ +public enum WizLightingColorMode { + // Full color mode + RGBMode("Full Color"), + // Tunable white (color temperature) mode + CTMode("Tunable White"), + // Dimming only + SingleColorMode("Dimming Only"); + + private String colorMode; + + private WizLightingColorMode(final String colorMode) { + this.colorMode = colorMode; + } + + /** + * Gets the colorMode name for request colorMode + * + * @return the colorMode name + */ + public String getColorMode() { + return colorMode; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java new file mode 100644 index 0000000000000..1592fdeeb2bd1 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java @@ -0,0 +1,107 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.enums; + +import java.util.HashMap; +import java.util.Map; + +/** + * This enum represents the possible scene modes. + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ +public enum WizLightingLightMode { + Ocean("Ocean", 1), + Romance("Romance", 2), + Sunset("Sunset", 3), + Party("Party", 4), + Fireplace("Fireplace", 5), + CozyWhite("Cozy White", 6), + Forest("Forest", 7), + PastelColors("Pastel Colors", 8), + Wakeup("Wakeup", 9), + BedTime("Bed Time", 10), + WarmWhite("Warm White", 11), + Daylight("Daylight", 12), + CoolWhite("Cool White", 13), + NightLight("Night Light", 14), + Focus("Focus", 15), + Relax("Relax", 16), + TrueColors("True Colors", 17), + TVTime("TV Time", 18), + PlantGrowth("Plant Growth", 19), + Spring("Spring", 20), + Summer("Summer", 21), + Fall("Fall", 22), + DeepDive("Deep Dive", 23), + Jungle("Jungle", 24), + Mojito("Mojito", 25), + Club("Club", 26), + Christmas("Christmas", 27), + Halloween("Halloween", 28), + Candlelight("Candlelight", 29), + GoldenWhite("Golden White", 30), + Pulse("Pulse", 31), + Steampunk("Steampunk", 32); + + private String colorModeName; + private int sceneId; + + private WizLightingLightMode(final String colorModeName, final int sceneId) { + this.colorModeName = colorModeName; + this.sceneId = sceneId; + } + + /** + * Gets the colorMode name for request colorMode + * + * @return the colorMode name + */ + public String getColorMode() { + return colorModeName; + } + + public int getSceneId() { + return sceneId; + } + + private static final Map LIGHT_MODE_MAP_BY_ID; + private static final Map LIGHT_MODE_MAP_BY_NAME; + + static { + LIGHT_MODE_MAP_BY_ID = new HashMap(); + LIGHT_MODE_MAP_BY_NAME = new HashMap(); + + for (WizLightingLightMode v : WizLightingLightMode.values()) { + LIGHT_MODE_MAP_BY_ID.put(v.sceneId, v); + LIGHT_MODE_MAP_BY_NAME.put(v.colorModeName.toLowerCase().replaceAll("\\W+", ""), v); + } + } + + public static WizLightingLightMode fromSceneId(int id) { + WizLightingLightMode r = null; + if (id > 0 && id < 33) { + r = LIGHT_MODE_MAP_BY_ID.get(id); + } + return r; + } + + public static WizLightingLightMode fromSceneName(String name) { + WizLightingLightMode r = null; + if (name != null && !"".equals(name)) { + r = LIGHT_MODE_MAP_BY_NAME.get(name.toLowerCase().replaceAll("\\W+", "")); + } + return r; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java new file mode 100644 index 0000000000000..e1cc8294777e5 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java @@ -0,0 +1,142 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.enums; + +import com.google.gson.annotations.SerializedName; + +/** + * This enum represents the available WiZ Lighting Request Methods + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +public enum WizLightingMethodType { + /** + * Registration - used to "register" with the bulb: This notifies the bult that + * it you want it to send you heartbeat sync packets. + * NOTE: The homeId value is optional, other values are required + * NOTE: There is no need to register before calling other methods. + * Example Request: + * {"method": "registration", "id": 1, "params": + * {"phoneIp": "10.0.0.xxx", "register": true, "homeId": xxxxxx, "phoneMac": "macOfopenHAB"}} + * Example Response: + * {"method": "registration", "id": 1, "env": "pro", "result": + * {"mac": "macOfopenHAB", "success": true}} + */ + @SerializedName("registration") + Registration("registration"), + /** + * Pulse - tells the bulb to briely change brightness (by delta % for duration ms) + * Example Request: + * {"method": "pulse", "id": 22, "params": {"delta": -30, "duration": 900}} + * Example Response: + * {"method": "pulse", "id": 22, "env": "pro", "result": {"success": true}} + */ + @SerializedName("pulse") + Pulse("pulse"), + /** + * setPilot - used to tell the bulb to change color/temp/state + * Example Request: + * {"method": "setPilot", "id": 24, "params": {"state": 1}} + * Example Response: + * {"method": "setPilot", "id": 24, "env": "pro", "result": {"success": true}} + */ + @SerializedName("setPilot") + SetPilot("setPilot"), + /** + * getPilot - gets the current bulb state - no paramters need to be included + * Example Request: + * {"method": "getPilot", "id": 24} + * Example Response: + * {"method": "getPilot", "id": 22, "env": "pro", "result": {"mac": + * "a8bb508f570a", "rssi":-76, "state": true, "sceneId": 0, "temp": 2700, + * "dimming": 42, "schdPsetId": 5}} + */ + @SerializedName("getPilot") + GetPilot("getPilot"), + /** + * syncPilot - sent by the bulb as heart-beats + * Example: + * {"method": "syncPilot", "id": 218, "env": "pro", "params": + * { "mac": "theBulbMacAddress", "rssi": -72, "src": "udp", "state": true, "sceneId": 0, + * "temp": 3362, "dimming": 69, "schdPsetId": 5}} + * Another Example: + * {"method": "syncPilot", "id": 219, "env": "pro", "params": + * { "mac": "theBulbMacAddress", "rssi": -72, "src": "hb", "mqttCd": 0, "state": true, + * "sceneId": 0, "temp": 3362, "dimming": 69, "schdPsetId": 5}} + */ + @SerializedName("syncPilot") + SyncPilot("syncPilot"), + /** + * getSystemConfig - gets the current system configuration - no paramters need + * to be included + * Example Request: + * {"method": "getSystemConfig", "id": 24} + * Example Response: + * {"method": "getSystemConfig", "id": 22, "env": "pro", + * "result": {"mac": "theBulbMacAddress", "homeId": xxxxxx, "roomId": xxxxxx, + * "homeLock": false, "pairingLock": false, "typeId": 0, "moduleName": + * "ESP01_SHRGB1C_31", "fwVersion": "1.15.2", "groupId": 0, "drvConf":[33,1]}} + */ + @SerializedName("getSystemConfig") + GetSystemConfig("getSystemConfig"), + /** + * setSystemConfig - presumably sets up the system + * I have NOT attempted to call this method + */ + @SerializedName("setSystemConfig") + SetSystemConfig("setSystemConfig"), + /** + * getWifiConfig - gets the current wifi configuration - no paramters need to be + * included + * Example Request: + * {"id": 22, "method": "getWifiConfig"} + * Example Response: + * {"method": "getWifiConfig", "id": 22, "env": "pro", "result": + * {:["encryptedString"]} + */ + @SerializedName("getWifiConfig") + GetWifiConfig("getWifiConfig"), + /** + * setWifiConfig - presumably sets up the system I have NOT attempted to use this method + */ + @SerializedName("setWifiConfig") + SetWifiConfig("setWifiConfig"), + /** + * firstBeat - set by a bulb upon power up + * Example: + * {"method": "firstBeat", "id": 0, "env": "pro", "params": + * {"mac": "theBulbMacAddress", "homeId": xxxxxx, "fwVersion": "1.15.2"}} + */ + @SerializedName("firstBeat") + FirstBeat("firstBeat"), + /** + * Unknown - using as a default for inproperly received responses + */ + UnknownMethod("unknownMethod"); + + private final String methodName; + + private WizLightingMethodType(final String methodName) { + this.methodName = methodName; + } + + /** + * Gets the method name for request method + * + * @return the method name + */ + public String getMethodName() { + return methodName; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java new file mode 100644 index 0000000000000..67d86400366fb --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java @@ -0,0 +1,62 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.enums; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import java.util.HashMap; +import java.util.Map; + +import org.openhab.core.thing.ThingTypeUID; + +/** + * This enum represents the possible scene modes. + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ +public enum WizLightingModuleType { + FullColorWifi("ESP01_SHRGB1C_31", THING_TYPE_COLOR_BULB), + TunableWhiteWifi("ESP56_SHTW3_01", THING_TYPE_TUNABLE_BULB), + DimmableWifi("TBD", THING_TYPE_DIMMABLE_BULB), + SmartPlug("TBD", THING_TYPE_SMART_PLUG); + + private final String moduleName; + private final ThingTypeUID thingTypeUID; + + private WizLightingModuleType(final String moduleName, final ThingTypeUID thingTypeUID) { + this.moduleName = moduleName; + this.thingTypeUID = thingTypeUID; + } + + /** + * Gets the colorMode name for request colorMode + * + * @return the colorMode name + */ + public String getModuleName() { + return moduleName; + } + + private static final Map MODULE_NAME_MAP; + static { + MODULE_NAME_MAP = new HashMap(); + for (WizLightingModuleType v : WizLightingModuleType.values()) { + MODULE_NAME_MAP.put(v.moduleName, v.thingTypeUID); + } + } + + public static ThingTypeUID getThingTypeUIDFromModuleName(String moduleName) { + return MODULE_NAME_MAP.get(moduleName); + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java new file mode 100644 index 0000000000000..e2a6a771347c1 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java @@ -0,0 +1,756 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.handler; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.core.thing.Thing.*; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.SocketTimeoutException; +import java.util.HashMap; +import java.util.Map; +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.binding.wizlighting.internal.config.WizLightingDeviceConfiguration; +import org.openhab.binding.wizlighting.internal.entities.ColorRequestParam; +import org.openhab.binding.wizlighting.internal.entities.ColorTemperatureRequestParam; +import org.openhab.binding.wizlighting.internal.entities.DimmingRequestParam; +import org.openhab.binding.wizlighting.internal.entities.FanStateRequestParam; +import org.openhab.binding.wizlighting.internal.entities.Param; +import org.openhab.binding.wizlighting.internal.entities.RegistrationRequestParam; +import org.openhab.binding.wizlighting.internal.entities.SceneRequestParam; +import org.openhab.binding.wizlighting.internal.entities.SpeedRequestParam; +import org.openhab.binding.wizlighting.internal.entities.StateRequestParam; +import org.openhab.binding.wizlighting.internal.entities.SystemConfigResult; +import org.openhab.binding.wizlighting.internal.entities.WizLightingRequest; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wizlighting.internal.entities.WizLightingSyncState; +import org.openhab.binding.wizlighting.internal.enums.WizLightingLightMode; +import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; +import org.openhab.binding.wizlighting.internal.utils.ValidationUtils; +import org.openhab.binding.wizlighting.internal.utils.WizLightingPacketConverter; +import org.openhab.core.config.core.Configuration; +import org.openhab.core.library.types.DateTimeType; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.HSBType; +import org.openhab.core.library.types.IncreaseDecreaseType; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.PercentType; +import org.openhab.core.library.types.QuantityType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.Units; +import org.openhab.core.thing.ChannelUID; +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.types.Command; +import org.openhab.core.types.RefreshType; +import org.openhab.core.types.UnDefType; +import org.openhab.core.util.ColorUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link WizLightingHandler} is responsible for handling commands, which + * are sent to one of the channels. + * + * @author Sriram Balakrishnan - Initial contribution + */ +@NonNullByDefault +public class WizLightingHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(WizLightingHandler.class); + + private @NonNullByDefault({}) WizLightingDeviceConfiguration config; + private RegistrationRequestParam registrationInfo; + private int homeId; + + private WizLightingSyncState mostRecentState; + + private final WizLightingPacketConverter converter = new WizLightingPacketConverter(); + private @Nullable ScheduledFuture keepAliveJob; + private long latestUpdate = -1; + private long latestOfflineRefresh = -1; + private int requestId = 0; + private final boolean isFan; + + private volatile boolean disposed; + private volatile boolean fullyInitialized; + + /** + * Default constructor. + * + * @param thing the thing of the handler. + */ + public WizLightingHandler(final Thing thing, final RegistrationRequestParam registrationPacket) { + super(thing); + this.registrationInfo = registrationPacket; + this.mostRecentState = new WizLightingSyncState(); + this.isFan = thing.getThingTypeUID().equals(THING_TYPE_CEILING_FAN); + fullyInitialized = false; + } + + @Override + public void handleCommand(final ChannelUID channelUID, final Command command) { + if (hasConfigurationError() || disposed || !fullyInitialized) { + logger.debug( + "[{}] WiZ handler for blub {} received command {} on channel {} but is not yet prepared to handle it.", + config.bulbIpAddress, config.bulbMacAddress, command, channelUID); + return; + } + + if (command instanceof RefreshType) { + long now = System.currentTimeMillis(); + long timePassedFromLastUpdateInSeconds = (now - latestUpdate) / 1000; + // Be patient... + if (latestUpdate < 0 || timePassedFromLastUpdateInSeconds > 5) { + getPilot(); + } + return; + } + + switch (channelUID.getId()) { + case CHANNEL_COLOR: + if (command instanceof HSBType) { + handleHSBCommand((HSBType) command); + } else if (command instanceof PercentType) { + handlePercentCommand((PercentType) command); + } else if (command instanceof OnOffType) { + handleOnOffCommand((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + handleIncreaseDecreaseCommand(command == IncreaseDecreaseType.INCREASE); + } + break; + + case CHANNEL_TEMPERATURE: + if (command instanceof PercentType) { + handleTemperatureCommand((PercentType) command); + } else if (command instanceof OnOffType) { + handleTemperatureCommand( + ((OnOffType) command) == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); + } else if (command instanceof IncreaseDecreaseType) { + handleIncreaseDecreaseTemperatureCommand(command == IncreaseDecreaseType.INCREASE); + } + break; + + case CHANNEL_TEMPERATURE_ABS: + QuantityType kelvinQt; + if (command instanceof QuantityType commandQt + && (kelvinQt = commandQt.toInvertibleUnit(Units.KELVIN)) != null) { + handleTemperatureCommand(kelvinQt.intValue()); + } else { + handleTemperatureCommand(Integer.valueOf(command.toString())); + } + + case CHANNEL_BRIGHTNESS: + if (command instanceof PercentType) { + handlePercentCommand((PercentType) command); + } else if (command instanceof OnOffType) { + handleOnOffCommand((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + handleIncreaseDecreaseCommand(command == IncreaseDecreaseType.INCREASE); + } + break; + + case CHANNEL_STATE: + if (command instanceof OnOffType) { + if (isFan) { + handleFanOnOffCommand((OnOffType) command); + } else { + handleOnOffCommand((OnOffType) command); + } + } + break; + + case CHANNEL_MODE: + // TODO: handle fan mode + handleLightModeCommand(command); + break; + + case CHANNEL_SPEED: + // TODO: handle fan speed + if (command instanceof PercentType) { + handleSpeedCommand((PercentType) command); + } else if (command instanceof OnOffType) { + handleSpeedCommand(((OnOffType) command) == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); + } else if (command instanceof IncreaseDecreaseType) { + handleIncreaseDecreaseSpeedCommand(command == IncreaseDecreaseType.INCREASE); + } + break; + + case CHANNEL_REVERSE: + // TODO: handle fan direction + break; + } + } + + @Override + public void handleRemoval() { + disposed = true; + fullyInitialized = false; + // stop update thread + ScheduledFuture keepAliveJob = this.keepAliveJob; + if (keepAliveJob != null) { + keepAliveJob.cancel(true); + this.keepAliveJob = null; + } + super.handleRemoval(); + } + + private void handleLightModeCommand(Command command) { + String commandAsString = command.toString(); + + Integer commandAsInt = Integer.MIN_VALUE; + WizLightingLightMode commandAsLightMode = null; + + try { + commandAsInt = Integer.parseInt(commandAsString); + } catch (Exception ex) { + } + + if (commandAsInt > 0) { + commandAsLightMode = WizLightingLightMode.fromSceneId(commandAsInt); + } + + if (commandAsLightMode == null) { + commandAsLightMode = WizLightingLightMode.fromSceneName(commandAsString); + } + + if (commandAsLightMode != null) { + mostRecentState.sceneId = commandAsLightMode.getSceneId(); + setPilotCommand(new SceneRequestParam(commandAsLightMode.getSceneId())); + } else { + logger.warn("[{}] Command [{}] not a recognized Light Mode!", config.bulbIpAddress); + } + } + + private void handleHSBCommand(HSBType hsb) { + if (hsb.getBrightness().intValue() == 0) { + logger.debug("[{}] Zero intensity requested, turning bulb off.", config.bulbIpAddress); + setPilotCommand(new StateRequestParam(false)); + } else { + setPilotCommand(new ColorRequestParam(hsb)); + } + mostRecentState.setHSBColor(hsb); + } + + private void handlePercentCommand(PercentType brightness) { + if (brightness.equals(PercentType.ZERO)) { + logger.debug("[{}] Zero brightness requested, turning bulb off.", config.bulbIpAddress); + setPilotCommand(new StateRequestParam(false)); + } else { + setPilotCommand(new DimmingRequestParam(brightness.intValue())); + } + mostRecentState.dimming = brightness.intValue(); + } + + private void handleOnOffCommand(OnOffType onOff) { + setPilotCommand(new StateRequestParam(onOff == OnOffType.ON ? true : false)); + mostRecentState.state = onOff == OnOffType.ON; + } + + private void handleFanOnOffCommand(OnOffType onOff) { + setPilotCommand(new FanStateRequestParam(onOff == OnOffType.ON ? 1 : 0)); + mostRecentState.state = onOff == OnOffType.ON; + } + + private void handleIncreaseDecreaseCommand(boolean isIncrease) { + int oldDimming = mostRecentState.dimming; + int newDimming = 50; + if (isIncrease) { + newDimming = Math.min(100, oldDimming + 5); + } else { + newDimming = Math.max(10, oldDimming - 5); + } + logger.debug("[{}] Changing bulb brightness from {}% to {}%.", config.bulbIpAddress, oldDimming, newDimming); + handlePercentCommand(new PercentType(newDimming)); + } + + private void handleTemperatureCommand(PercentType temperature) { + setPilotCommand(new ColorTemperatureRequestParam(temperature)); + mostRecentState.setTemperaturePercent(temperature); + } + + private void handleTemperatureCommand(int temperature) { + setPilotCommand(new ColorTemperatureRequestParam(temperature)); + mostRecentState.setTemperature(temperature); + } + + private void handleIncreaseDecreaseTemperatureCommand(boolean isIncrease) { + int oldTempPct = mostRecentState.getTemperaturePercent().intValue(); + int newTempPct = 50; + if (isIncrease) { + newTempPct = Math.min(100, oldTempPct + 5); + } else { + newTempPct = Math.max(0, oldTempPct - 5); + } + logger.debug("[{}] Changing color temperature from {}% to {}%.", config.bulbIpAddress, oldTempPct, newTempPct); + handleTemperatureCommand(new PercentType(newTempPct)); + } + + private void handleSpeedCommand(PercentType speed) { + // NOTE: We cannot set the speed without also setting the scene + int currentScene = mostRecentState.sceneId; + setPilotCommand(new SpeedRequestParam(currentScene, speed.intValue())); + mostRecentState.speed = speed.intValue(); + } + + private void handleIncreaseDecreaseSpeedCommand(boolean isIncrease) { + int oldSpeed = mostRecentState.speed; + int newSpeed = 50; + if (isIncrease) { + newSpeed = Math.min(100, oldSpeed + 5); + } else { + newSpeed = Math.max(10, oldSpeed - 5); + } + handleSpeedCommand(new PercentType(newSpeed)); + } + + /** + * Starts one thread that querys the state of the socket, after the defined + * refresh interval. + */ + private synchronized void initGetStatusAndKeepAliveThread() { + ScheduledFuture keepAliveJob = this.keepAliveJob; + if (keepAliveJob != null) { + keepAliveJob.cancel(true); + } + + Runnable runnable = () -> { + long now = System.currentTimeMillis(); + long timePassedFromLastUpdateInSeconds = (now - latestUpdate) / 1000; + long timePassedFromLastRefreshInSeconds = (now - latestOfflineRefresh) / 1000; + + // If the bulb has an online status, check if we it's been too long since the + // last response and re-set offline accordingly + if (getThing().getStatus() == ThingStatus.ONLINE) { + logger.trace("[{}] MAC address: {} Latest Update: {} Now: {} Delta: {} seconds", config.bulbIpAddress, + config.bulbMacAddress, latestUpdate, now, timePassedFromLastUpdateInSeconds); + + boolean considerThingOffline = (latestUpdate < 0) + || (timePassedFromLastUpdateInSeconds > MARK_OFFLINE_AFTER_SEC); + if (considerThingOffline) { + logger.debug( + "[{}] Since no updates have been received from mac address {} in {} seconds, setting its status to OFFLINE and discontinuing polling.", + config.bulbIpAddress, config.bulbMacAddress, MARK_OFFLINE_AFTER_SEC); + updateStatus(ThingStatus.OFFLINE); + + } + } + + // If we're not offline ither re-register for heart-beats or request status + if (getThing().getStatus() != ThingStatus.OFFLINE) { + if (config.useHeartBeats) { + // If we're using 5s heart-beats, we must re-register every 30s to maintain + // connection + logger.debug("[{}] Re-registering for heart-beats.", config.bulbIpAddress); + registerWithBulb(); + } else { + // If we're not using heart-beats, just request the current status + logger.debug("[{}] Polling for status from bulb at {}.", config.bulbIpAddress, + config.bulbMacAddress); + getPilot(); + } + + // Else if we are offline, but it's been a while, re-check if the bulb re-appeared + } else if (timePassedFromLastRefreshInSeconds > config.reconnectInterval * 60) { + // Request the current status + logger.debug("[{}] Checking for reappearance of offline bulb at {}.", config.bulbIpAddress, + config.bulbMacAddress); + latestOfflineRefresh = now; + getPilot(); + } + }; + /** + * Schedule the keep-alive job. + * + * The scheduling inteval is: + * - every 30 seconds for online bulbs receiving heart-beats + * - every config.updateInterval for other online bulbs + */ + long updateIntervalInUse = config.useHeartBeats ? 30 : config.updateInterval; + logger.debug("[{}] Scheduling reoccuring keep alive for every {} seconds for bulb at {}.", config.bulbIpAddress, + updateIntervalInUse, config.bulbMacAddress); + this.keepAliveJob = scheduler.scheduleWithFixedDelay(runnable, 1, updateIntervalInUse, TimeUnit.SECONDS); + } + + @Override + public void initialize() { + this.config = getConfigAs(WizLightingDeviceConfiguration.class); + fullyInitialized = false; + disposed = false; + + // set the thing status to UNKNOWN temporarily + updateStatus(ThingStatus.UNKNOWN); + if (ValidationUtils.isMacNotValid(config.bulbMacAddress)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "MAC address is not valid"); + } + updateBulbProperties(); + initGetStatusAndKeepAliveThread(); + fullyInitialized = true; + } + + @Override + public void dispose() { + disposed = true; + fullyInitialized = false; + // stop update thread + ScheduledFuture keepAliveJob = this.keepAliveJob; + if (keepAliveJob != null) { + keepAliveJob.cancel(true); + this.keepAliveJob = null; + } + } + + private synchronized void getPilot() { + WizLightingResponse response = sendRequestPacket(WizLightingMethodType.GetPilot, null); + if (response != null) { + WizLightingSyncState rParam = response.getSyncState(); + if (rParam != null) { + updateTimestamps(); + updateStatesFromParams(rParam); + } else { + logger.trace("[{}] No parameters in getPilot response!", config.bulbIpAddress); + } + } else { + logger.trace("[{}] No response from getPilot request!", config.bulbIpAddress); + } + } + + /** + * Method called by {@link WizLightingMediator} when any "unsolicited" messages + * come in on the listening socket and appear to be a WiZ bulb. "Unsolicited" + * messages from the bulb are could be: + * - a "firstBeat" broadcast to the subnet by the bulb on first powering up + * - an "hb" (heartbeat) specifically directed to OpenHab within 30 seconds of registration + * - or a response to a registration request broadcast by this binding to all bulbs on the subnet + * + * @note The mediator finds the correct handler for the bulb based on the (unchanging) bulb + * MAC address. If the mediator matches a message to the handler by MAC address, but the IP address + * the message came from doesn't match the bulb's configured IP address, this will update the + * bulb's configuration to reflect whatever the current IP is. + * + * @param receivedMessage the received {@link WizLightingResponse}. + */ + public synchronized void newReceivedResponseMessage(final WizLightingResponse receivedMessage) { + Boolean updatePropertiesAfterParams = false; + + // Check if the bulb still has the same IP address it had previously + // If not, we need to update the configuration for the thing. + if (receivedMessage.getWizResponseIpAddress() != MISSING_INVALID_IP_ADDRESS + && receivedMessage.getWizResponseIpAddress() != this.getBulbIpAddress()) { + // get the old config + Configuration priorConfig = getConfig(); + // change the ip address property + priorConfig.put(CONFIG_IP_ADDRESS, receivedMessage.getWizResponseIpAddress()); + // save the changes to the thing + updateConfiguration(priorConfig); + // and then refresh the config within the handler + this.config = getConfigAs(WizLightingDeviceConfiguration.class); + // finally, make note that we want to update properties + updatePropertiesAfterParams = true; + } + + // Grab the ID number and mark the bulb online + requestId = receivedMessage.getId(); + updateTimestamps(); + + // Update the state from the parameters, if possible + WizLightingSyncState params = receivedMessage.getSyncState(); + if (params != null) { + updateStatesFromParams(params); + } + + // After updating state, we'll update all other bulb parameters from bulbs that + // presented with a new IP address. + if (updatePropertiesAfterParams) { + updateBulbProperties(); + } + } + + /** + * Updates the channel states based on incoming parameters + * + * @param receivedParam The received {@link WizLightingSyncState} + */ + private synchronized void updateStatesFromParams(final WizLightingSyncState receivedParam) { + // Save the current state + this.mostRecentState = receivedParam; + + if (hasConfigurationError() || disposed) { + return; + } + + if (isFan) { + updateFanStatesFromParams(receivedParam); + } else { + updateLightStatesFromParams(receivedParam); + } + + // update signal strength + if (receivedParam.rssi != 0) { + int strength = -1; + if (receivedParam.rssi < -90) { + strength = 0; + } else if (receivedParam.rssi < -80) { + strength = 1; + } else if (receivedParam.rssi < -70) { + strength = 2; + } else if (receivedParam.rssi < -67) { + strength = 3; + } else { + strength = 4; + } + updateState(CHANNEL_RSSI, new DecimalType(strength)); + } + } + + /** + * Updates the channel states for a light based on incoming parameters + * + * @param receivedParam The received {@link WizLightingSyncState} + */ + private void updateLightStatesFromParams(final WizLightingSyncState receivedParam) { + if (!receivedParam.state) { + updateState(CHANNEL_COLOR, HSBType.BLACK); + updateState(CHANNEL_BRIGHTNESS, PercentType.ZERO); + updateState(CHANNEL_STATE, OnOffType.OFF); + updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); + updateState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); + } else { + updateState(CHANNEL_BRIGHTNESS, new PercentType(receivedParam.dimming)); + updateState(CHANNEL_STATE, OnOffType.ON); + switch (receivedParam.getColorMode()) { + case RGBMode: + logger.trace( + "[{}] Received color values - R: {} G: {} B: {} W: {} C: {} Dimming: {}; translate to HSBType: {}", + config.bulbIpAddress, receivedParam.r, receivedParam.g, receivedParam.b, receivedParam.w, + receivedParam.c, receivedParam.dimming, receivedParam.getHSBColor()); + + updateState(CHANNEL_COLOR, receivedParam.getHSBColor()); + updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); + updateState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); + break; + case CTMode: + double[] xy = ColorUtil.kelvinToXY(receivedParam.getTemperature()); + HSBType color = ColorUtil.xyToHsb(xy); + updateState(CHANNEL_COLOR, new HSBType(color.getHue(), color.getSaturation(), + new PercentType(receivedParam.getDimming()))); + updateState(CHANNEL_TEMPERATURE, receivedParam.getTemperaturePercent()); + updateState(CHANNEL_TEMPERATURE_ABS, + new QuantityType<>(receivedParam.getTemperature(), Units.KELVIN)); + break; + case SingleColorMode: + updateState(CHANNEL_COLOR, new HSBType(DecimalType.ZERO, PercentType.ZERO, + new PercentType(receivedParam.getDimming()))); + updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); + updateState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); + break; + } + } + + updateState(CHANNEL_MODE, new StringType(String.valueOf(receivedParam.sceneId))); + updateState(CHANNEL_SPEED, new PercentType(receivedParam.speed)); + } + + /** + * Updates the channel states for a fan based on incoming parameters + * + * @param receivedParam The received {@link WizLightingSyncState} + */ + private void updateFanStatesFromParams(final WizLightingSyncState receivedParam) { + updateState(CHANNEL_STATE, new DecimalType(receivedParam.fanState)); + updateState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); + updateState(CHANNEL_REVERSE, new DecimalType(receivedParam.fanRevrs)); + updateState(CHANNEL_MODE, new DecimalType(receivedParam.fanMode)); + } + + /** + * Sends {@link WizLightingRequest} to the passed {@link InetAddress}. + * + * @param requestPacket the {@link WizLightingRequest}. + * @param address the {@link InetAddress}. + */ + private synchronized @Nullable WizLightingResponse sendRequestPacket(final WizLightingMethodType method, + final @Nullable Param param) { + DatagramSocket dsocket = null; + try { + InetAddress address = InetAddress.getByName(config.bulbIpAddress); + if (address != null) { + WizLightingRequest request = new WizLightingRequest(method, param); + request.setId(requestId++); + + byte[] message = this.converter.transformToByteMessage(request); + logger.trace("Raw packet to send: {}", message); + + // Initialize a datagram packet with data and address + DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_BULB_UDP_PORT); + + // Create a datagram socket, send the packet through it, close it. + dsocket = new DatagramSocket(null); + dsocket.setReuseAddress(true); + dsocket.setBroadcast(true); + dsocket.setSoTimeout(500); // Timeout in 500ms + dsocket.send(packet); + logger.debug("[{}] Sent packet to address: {} and port {}", config.bulbIpAddress, address, + DEFAULT_BULB_UDP_PORT); + + byte[] responseMessage = new byte[1024]; + packet = new DatagramPacket(responseMessage, responseMessage.length); + dsocket.receive(packet); + + return converter.transformResponsePacket(packet); + } + } catch (SocketTimeoutException e) { + logger.trace("[{}] Socket timeout after sending command; no response from {} within 500ms", + config.bulbIpAddress, config.bulbMacAddress); + } catch (IOException exception) { + logger.debug("[{}] Something wrong happened when sending the packet to port {}... msg: {}", + config.bulbIpAddress, DEFAULT_BULB_UDP_PORT, exception.getMessage()); + } finally { + if (dsocket != null) { + dsocket.close(); + } + } + return null; + } + + /** + * Sends a setPilot request and checks for success + */ + private synchronized boolean setPilotCommand(final @Nullable Param param) { + WizLightingResponse response = sendRequestPacket(WizLightingMethodType.SetPilot, param); + if (response != null) { + boolean setSucceeded = response.getResultSuccess(); + if (setSucceeded) { + // can't process this response it doens't have a syncstate, so request updated state + // let the getPilot response update the timestamps + try { + // wait for state change to apply + Thread.sleep(1000L); + } catch (InterruptedException e) { + } + getPilot(); + return setSucceeded; + } + } + return false; + } + + /** + * Makes note of the latest timestamps and sets the bulb online + */ + private synchronized void updateTimestamps() { + if (hasConfigurationError() || disposed) { + return; + } + updateStatus(ThingStatus.ONLINE); + latestUpdate = System.currentTimeMillis(); + latestOfflineRefresh = System.currentTimeMillis(); + updateState(CHANNEL_LAST_UPDATE, new DateTimeType()); + } + + /** + * Asks the bulb for its current system configuration + */ + private synchronized void updateBulbProperties() { + if (hasConfigurationError() || disposed) { + return; + } + WizLightingResponse registrationResponse = sendRequestPacket(WizLightingMethodType.GetSystemConfig, null); + if (registrationResponse != null) { + SystemConfigResult responseResult = registrationResponse.getSystemConfigResults(); + if (responseResult != null) { + // Update all the thing properties based on the result + Map thingProperties = new HashMap(); + thingProperties.put(PROPERTY_VENDOR, "WiZ Connected"); + thingProperties.put(PROPERTY_FIRMWARE_VERSION, responseResult.fwVersion); + thingProperties.put(PROPERTY_MAC_ADDRESS, responseResult.mac); + thingProperties.put(PROPERTY_IP_ADDRESS, registrationResponse.getWizResponseIpAddress()); + thingProperties.put(PROPERTY_HOME_ID, String.valueOf(responseResult.homeId)); + thingProperties.put(PROPERTY_ROOM_ID, String.valueOf(responseResult.roomId)); + thingProperties.put(PROPERTY_HOME_LOCK, String.valueOf(responseResult.homeLock)); + thingProperties.put(PROPERTY_PAIRING_LOCK, String.valueOf(responseResult.pairingLock)); + thingProperties.put(PROPERTY_TYPE_ID, String.valueOf(responseResult.typeId)); + thingProperties.put(PROPERTY_MODULE_NAME, responseResult.moduleName); + thingProperties.put(PROPERTY_GROUP_ID, String.valueOf(responseResult.groupId)); + updateProperties(thingProperties); + updateTimestamps(); + } else { + logger.debug( + "[{}] Received response to getConfigRequest from bulb at {}, but id did not contain bulb configuration information.", + config.bulbIpAddress, config.bulbMacAddress); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } + } else { + logger.debug("[{}] No response to registration request from bulb at {}", config.bulbIpAddress, + config.bulbMacAddress); + // Not calling it "gone" because it's probably just been powered off and will beback any time + updateStatus(ThingStatus.OFFLINE); + } + } + + /** + * Registers with the bulb - this tells the bulb to begin sending 5-second + * heartbeat (hb) status updates. Status updates are sent by the bulb every 5 + * sec and on any state change for 30s after registration. For continuous + * heart-beats the registration must be re-sent after 30s. + */ + private synchronized void registerWithBulb() { + WizLightingResponse registrationResponse = sendRequestPacket(WizLightingMethodType.Registration, + this.registrationInfo); + if (registrationResponse != null) { + if (registrationResponse.getResultSuccess()) { + updateTimestamps(); + } else { + logger.debug( + "[{}] Received response to getConfigRequest from bulb at {}, but id did not contain bulb configuration information.", + config.bulbIpAddress, config.bulbMacAddress); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } + } else { + logger.debug("[{}] No response to registration request from bulb at {}", config.bulbIpAddress, + config.bulbMacAddress); + // Not calling it "gone" because it's probably just been powered off and will be + // back any time + updateStatus(ThingStatus.OFFLINE); + } + } + + private boolean hasConfigurationError() { + ThingStatusInfo statusInfo = getThing().getStatusInfo(); + return statusInfo.getStatus() == ThingStatus.OFFLINE + && statusInfo.getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR; + } + + // SETTERS AND GETTERS + public String getBulbIpAddress() { + return config.bulbIpAddress; + } + + public String getBulbMacAddress() { + return config.bulbMacAddress; + } + + public int getHomeId() { + return homeId; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java new file mode 100644 index 0000000000000..33223ea669543 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java @@ -0,0 +1,87 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.handler; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.discovery.WizLightingDiscoveryService; +import org.openhab.binding.wizlighting.internal.entities.RegistrationRequestParam; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.core.net.NetworkAddressService; +import org.openhab.core.thing.Thing; + +/** + * The {@link WizLightingMediator} is responsible for receiving all the sync + * packets and route correctly to each handler. + * + * @author Sriram Balakrishnan - Initial contribution + * @author Joshua Freeman - pass through NetworkAddressService + */ +@NonNullByDefault +public interface WizLightingMediator { + + /** + * This method is called by the {@link WizLightingUpdateReceiverRunnable}, when + * one new message has been received. + * + * @param receivedMessage the {@link WizLightingResponse} message. + */ + void processReceivedPacket(final WizLightingResponse receivedMessage); + + /** + * Returns a {@link RegistrationRequestParam} based on the current OpenHAB + * connection. + * + */ + RegistrationRequestParam getRegistrationParams(); + + /** + * Registers a new {@link Thing} and the corresponding + * {@link WizLightingHandler}. + * + * @param thing the {@link Thing}. + * @param handler the {@link WizLightingHandler}. + */ + void registerThingAndWizBulbHandler(final Thing thing, final WizLightingHandler handler); + + /** + * Unregisters a {@link WizLightingHandler} by the corresponding {@link Thing}. + * + * @param thing the {@link Thing}. + */ + void unregisterWizBulbHandlerByThing(final Thing thing); + + /** + * Returns all the {@link Thing} registered. + * + * @returns all the {@link Thing}. + */ + Set getAllThingsRegistered(); + + /** + * Sets the discovery service to inform the user when one new thing has been + * found. + * + * @param discoveryService the discovery service. + */ + void setDiscoveryService(final @Nullable WizLightingDiscoveryService discoveryService); + + /** + * Gets the NetworkAddressService used to configure the mediator instance. + * + * @return networkAddressService + */ + NetworkAddressService getNetworkAddressService(); +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java new file mode 100644 index 0000000000000..820d8b90a0365 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java @@ -0,0 +1,247 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.handler; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import java.net.SocketException; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.discovery.WizLightingDiscoveryService; +import org.openhab.binding.wizlighting.internal.entities.RegistrationRequestParam; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wizlighting.internal.runnable.WizLightingUpdateReceiverRunnable; +import org.openhab.binding.wizlighting.internal.utils.NetworkUtils; +import org.openhab.core.net.NetworkAddressService; +import org.openhab.core.thing.Thing; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link WizLightingMediatorImpl} is responsible for receiving all the sync + * packets and route correctly to each handler. + * + * @author Sriram Balakrishnan - Initial contribution + * @author Joshua Freeman - pass through NetworkAddressService + */ +@Component(configurationPid = "WizLightingMediator", service = WizLightingMediator.class) +@NonNullByDefault +public class WizLightingMediatorImpl implements WizLightingMediator { + + private final Logger logger = LoggerFactory.getLogger(WizLightingMediatorImpl.class); + + private final Map handlersRegisteredByThing = new HashMap<>(); + + private @Nullable WizLightingUpdateReceiverRunnable receiver; + private @Nullable Thread wizLightingReceiverThread; + + private @Nullable WizLightingDiscoveryService wizlightingDiscoveryService; + + private final NetworkAddressService networkAddressService; + + /** + * Constructor for the mediator implementation. + * + * @param IllegalArgumentException if the timeout < 0 + */ + @Activate + public WizLightingMediatorImpl( + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC) NetworkAddressService networkAddressService) { + this.networkAddressService = networkAddressService; + this.initMediatorWizBulbUpdateReceiverRunnable(); + } + + /** + * Called at the service deactivation. + * + * @param componentContext the componentContext + */ + protected void deactivate(final ComponentContext componentContext) { + WizLightingUpdateReceiverRunnable receiver = this.receiver; + if (receiver != null) { + receiver.shutdown(); + } + } + + /** + * This method is called by the {@link WizLightingUpdateReceiverRunnable}, when + * one new message has been received. + * + * @param receivedMessage the {@link WizLightingResponse} message. + */ + @Override + public void processReceivedPacket(final WizLightingResponse receivedMessage) { + logger.debug("Received packet from: {} - {} with method: [{}]", receivedMessage.getWizResponseIpAddress(), + receivedMessage.getWizResponseMacAddress(), receivedMessage.getMethod()); + + String bulbIp = receivedMessage.getWizResponseIpAddress(); + String bulbMac = receivedMessage.getWizResponseMacAddress(); + + if (!bulbMac.equals(MISSING_INVALID_MAC_ADDRESS)) { + @Nullable + WizLightingHandler handler = this.getHandlerRegisteredByMac(bulbMac); + + if (handler != null) { + // deliver message to handler. + handler.newReceivedResponseMessage(receivedMessage); + } else if (!bulbIp.equals(MISSING_INVALID_IP_ADDRESS)) { + logger.debug("There is no handler registered for mac address: {}", + receivedMessage.getWizResponseMacAddress()); + WizLightingDiscoveryService discoveryServe = this.wizlightingDiscoveryService; + if (discoveryServe != null) { + discoveryServe.discoveredLight(bulbMac, bulbIp); + logger.trace("Sending a new thing to the discovery service. MAC: {} IP: {}", bulbMac, bulbIp); + } else { + logger.trace("There is no discovery service registered to receive the new bulb!"); + } + } + } else { + logger.warn("The sync response did not contain a valid mac address, it cannot be processed."); + } + } + + /** + * Register one new {@link Thing} and the corresponding + * {@link WizLightingHandler}. + * + * @param thing the {@link Thing}. + * @param handler the {@link WizLightingHandler}. + */ + @Override + public void registerThingAndWizBulbHandler(final Thing thing, final WizLightingHandler handler) { + this.handlersRegisteredByThing.put(thing, handler); + } + + /** + * Unregister one {@link WizLightingHandler} by the corresponding {@link Thing}. + * + * @param thing the {@link Thing}. + */ + @Override + public void unregisterWizBulbHandlerByThing(final Thing thing) { + this.handlersRegisteredByThing.remove(thing); + } + + /** + * Utility method to get the registered thing handler in mediator by the mac + * address. + * + * @param bulbMacAddress the mac address of the thing of the handler. + * @return {@link WizLightingHandler} if found. + */ + private @Nullable WizLightingHandler getHandlerRegisteredByMac(final String bulbMacAddress) { + WizLightingHandler searchedHandler = null; + for (WizLightingHandler handler : this.handlersRegisteredByThing.values()) { + if (bulbMacAddress.equalsIgnoreCase(handler.getBulbMacAddress())) { + searchedHandler = handler; + // don't spend more computation. Found the handler. + break; + } + } + return searchedHandler; + } + + /** + * Inits the mediator WizBulbUpdateReceiverRunnable thread. This thread is + * responsible to receive all packets from Wiz Bulbs, and redirect the messages + * to mediator. + */ + private void initMediatorWizBulbUpdateReceiverRunnable() { + WizLightingUpdateReceiverRunnable receiver = this.receiver; + Thread receiverThread = this.wizLightingReceiverThread; + // try with handler port if is null + if ((receiver == null) + || ((receiverThread != null) && (receiverThread.isInterrupted() || !receiverThread.isAlive()))) { + try { + logger.trace("Receiver thread is either null, interrupted, or dead."); + WizLightingUpdateReceiverRunnable newReceiver = new WizLightingUpdateReceiverRunnable(this, + DEFAULT_LISTENER_UDP_PORT); + Thread newThread = new Thread(newReceiver); + newThread.setDaemon(true); + newThread.start(); + newThread.setName("wizLightingReceiverThread"); + this.receiver = newReceiver; + this.wizLightingReceiverThread = newThread; + } catch (SocketException e) { + logger.debug("Cannot start the socket with default port {}...", e.getMessage()); + } + } + } + + /** + * Returns all the {@link Thing} registered. + * + * @returns all the {@link Thing}. + */ + @Override + public Set getAllThingsRegistered() { + return this.handlersRegisteredByThing.keySet(); + } + + private String getMyIpAddress() { + String myIpAddress = networkAddressService.getPrimaryIpv4HostAddress(); + if (myIpAddress == null) { + logger.warn("Network interface did not return an IP address!"); + return "OHIPAddress"; + } + return myIpAddress; + } + + private String getMyMacAddress() { + String myMacAddress; + try { + myMacAddress = NetworkUtils.getMyMacAddress(getMyIpAddress()); + if (myMacAddress == null) { + logger.warn("No network interface could be found. MAC of OpenHab device is unknown."); + return "OHMACAddress"; + } + } catch (Exception e) { + logger.warn("MAC Address of openHAB device is invalid."); + return "OHMACAddress"; + } + return myMacAddress; + } + + /** + * Returns a {@link RegistrationRequestParam} based on the current OpenHAB + * connection. + * + */ + public RegistrationRequestParam getRegistrationParams() { + return new RegistrationRequestParam(getMyIpAddress(), true, 0, getMyMacAddress()); + } + + @Override + public void setDiscoveryService(final @Nullable WizLightingDiscoveryService discoveryService) { + this.wizlightingDiscoveryService = discoveryService; + } + + public @Nullable WizLightingDiscoveryService getDiscoveryService() { + return this.wizlightingDiscoveryService; + } + + @Override + public NetworkAddressService getNetworkAddressService() { + return this.networkAddressService; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java new file mode 100644 index 0000000000000..2c21162202bcc --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java @@ -0,0 +1,142 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.runnable; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetSocketAddress; +import java.net.SocketException; +import java.net.SocketTimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wizlighting.internal.handler.WizLightingMediator; +import org.openhab.binding.wizlighting.internal.utils.WizLightingPacketConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This Thread is responsible to receive all sync messages and redirect them to + * {@link WizLightingMediator}. + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class WizLightingUpdateReceiverRunnable implements Runnable { + + private static final int TIMEOUT_TO_DATAGRAM_RECEPTION_MILLISECONDS = 15000; + + private final Logger logger = LoggerFactory.getLogger(WizLightingUpdateReceiverRunnable.class); + + private DatagramSocket datagramSocket; + private final WizLightingMediator mediator; + private final WizLightingPacketConverter packetConverter = new WizLightingPacketConverter(); + + private boolean shutdown; + private int listeningPort; + + /** + * Constructor of the receiver runnable thread. + * + * @param mediator the {@link WizLightingMediator} + * @param listeningPort the listening UDP port + * @throws SocketException is some problem occurs opening the socket. + */ + public WizLightingUpdateReceiverRunnable(final WizLightingMediator mediator, final int listeningPort) + throws SocketException { + this.listeningPort = listeningPort; + this.mediator = mediator; + + // Create a socket to listen on the port. + logger.debug("Opening socket and start listening UDP port: {}", listeningPort); + DatagramSocket dsocket = new DatagramSocket(null); + dsocket.setReuseAddress(true); + dsocket.setBroadcast(true); + dsocket.setSoTimeout(TIMEOUT_TO_DATAGRAM_RECEPTION_MILLISECONDS); + dsocket.bind(new InetSocketAddress(listeningPort)); + this.datagramSocket = dsocket; + + this.shutdown = false; + } + + @Override + public void run() { + try { + // Now loop forever, waiting to receive packets and redirect them to mediator. + while (!this.shutdown) { + datagramSocketHealthRoutine(); + + // Create a buffer to read datagrams into. If a + // packet is larger than this buffer, the + // excess will simply be discarded! + byte[] buffer = new byte[2048]; + + // Create a packet to receive data into the buffer + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + + // Wait to receive a datagram + try { + datagramSocket.receive(packet); + + // Redirect packet to the mediator + WizLightingResponse response = this.packetConverter.transformResponsePacket(packet); + if (response != null) { + this.mediator.processReceivedPacket(response); + } else { + logger.debug("No WizLightingResponse was parsed from returned packet"); + } + } catch (SocketTimeoutException e) { + logger.trace("No incoming data on port {} during {} ms socket was listening.", listeningPort, + TIMEOUT_TO_DATAGRAM_RECEPTION_MILLISECONDS); + } catch (IOException e) { + logger.debug("One exception has occurred: {} ", e.getMessage()); + } + } + } finally { + // close the socket + datagramSocket.close(); + } + } + + private void datagramSocketHealthRoutine() { + DatagramSocket datagramSocket = this.datagramSocket; + if (datagramSocket.isClosed() || !datagramSocket.isConnected()) { + logger.trace("Datagram Socket is disconnected or has been closed (probably timed out), reconnecting..."); + try { + // close the socket before trying to reopen + this.datagramSocket.close(); + logger.trace("Old socket closed."); + DatagramSocket dsocket = new DatagramSocket(null); + dsocket.setReuseAddress(true); + dsocket.setBroadcast(true); + dsocket.setSoTimeout(TIMEOUT_TO_DATAGRAM_RECEPTION_MILLISECONDS); + dsocket.bind(new InetSocketAddress(listeningPort)); + this.datagramSocket = dsocket; + logger.trace("Datagram Socket reconnected."); + } catch (SocketException exception) { + logger.warn("Problem creating one new socket on port {}. Error: {}", listeningPort, + exception.getLocalizedMessage()); + } + } + } + + /** + * Gracefully shutdown thread. Worst case takes TIMEOUT_TO_DATAGRAM_RECEPTION_MILLISECONDS to + * shutdown. + */ + public void shutdown() { + this.shutdown = true; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java new file mode 100644 index 0000000000000..ee641e4e517b8 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java @@ -0,0 +1,73 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.utils; + +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.rmi.UnknownHostException; +import java.util.Enumeration; + +/** + * Utility class to perform some network routines. + * + * @author Sriram Balakrishnan - Initial contribution + * @author Joshua Freeman - Modified to get MAC matching IP + * + */ +public final class NetworkUtils { + /** + * Returns the MAC address of the openHAB first network device. + * + * @return The MAC address of the openHAB network device. + * @throws UnknownHostException + * @throws SocketException + */ + public static String getMyMacAddress(String matchIP) throws UnknownHostException, SocketException { + String macAddress = null; + Enumeration networks = NetworkInterface.getNetworkInterfaces(); + while (networks.hasMoreElements()) { + NetworkInterface network = networks.nextElement(); + + if (network != null && networkMatchesIP(network, matchIP)) { + macAddress = convertBytesToMACString(network.getHardwareAddress()); + break; // Short circuit if we found it + } + } + return macAddress; + } + + private static boolean networkMatchesIP(NetworkInterface network, String ip) { + if (network != null && ip != null) { + for (InterfaceAddress interfaceAddress : network.getInterfaceAddresses()) { + String hostAddress = interfaceAddress.getAddress().getHostAddress(); + if (ip.equals(hostAddress)) { + return true; + } + } + } + + return false; + } + + private static String convertBytesToMACString(byte[] hardwareAddress) { + StringBuilder macAddressBuilder = new StringBuilder(); + if (hardwareAddress != null) { + for (int macAddressByteIndex = 0; macAddressByteIndex < hardwareAddress.length; macAddressByteIndex++) { + String macAddressHexByte = String.format("%02X", hardwareAddress[macAddressByteIndex]); + macAddressBuilder.append(macAddressHexByte); + } + } + return macAddressBuilder.toString(); + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java new file mode 100644 index 0000000000000..27b9a08bab943 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java @@ -0,0 +1,56 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Utility static class to perform some validations. + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public final class ValidationUtils { + + private ValidationUtils() { + // avoid instantiation. + } + + public static final String MAC_PATTERN = "^([0-9A-Fa-f]{2}[:-]*){5}([0-9A-Fa-f]{2})$"; + private static final Pattern VALID_PATTERN = Pattern.compile(ValidationUtils.MAC_PATTERN); + + /** + * Validates if one Mac address is valid. + * + * @param mac the mac, with or without : + * @return true if is valid. + */ + public static boolean isMacValid(final String mac) { + Matcher matcher = VALID_PATTERN.matcher(mac); + return matcher.matches(); + } + + /** + * Validates if one Mac address is not valid. + * + * @param mac the mac, with or without : + * @return true if is not valid. + */ + public static boolean isMacNotValid(final String macAddress) { + return !isMacValid(macAddress); + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java new file mode 100644 index 0000000000000..1ffbac11481db --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java @@ -0,0 +1,167 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.utils; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.library.types.DecimalType; +import org.openhab.core.library.types.HSBType; +import org.openhab.core.library.types.PercentType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utilities for converting colors and color temperures + * + * The full color WiZ bulbs can produce colors and various temperatures of + * "whites" by mixing any of the available LEDs: RGBWwarm = RGBWWCwarm = Red, + * Green, Blue, Warm White, Cool White. When operating in full color mode, the + * warm whites are used to increase saturation (RGBW style). Temperatures of + * white can also be called directly as K instead of mixing cw/ww (c/w) The + * colors and temperatures need to be converted to the HSBType/PercentType + * supported by openHAB. + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ + +@NonNullByDefault +public class WizColorConverter { + + private final Logger logger = LoggerFactory.getLogger(WizColorConverter.class); + + /** + * Converts an {@link DecimalType} hue and a {@link PercentType} saturation to + * red, green, blue, and white (RGBW) components. Because the WiZ bulbs keep + * dimming in a separate channel, we only take account hue and saturation for + * the color channels. When creating colors, the WiZ bulbs only use the warm + * white channel, the cool white channel is ignored. + * + * Taken from Tasmota HsToRGB + * + * @param hsbColor the {@link HSBType}. + * + * @return an interger array of the color components + */ + public int[] hsbToRgbw(HSBType hsb) { + double redD = 255.; + double greenD = 255.; + double blueD = 255.; + int red = 255; + int green = 255; + int blue = 255; + int white = 255; + + // Since we're going to use the white lights to control saturation, recalculate what + // the HSBvalue would be if the color was at full brightness and saturation + Double hue = hsb.getHue().doubleValue(); + Double sat255 = ((hsb.getSaturation().doubleValue()) / 100) * 255; + + if (sat255 > 0) { + int i = (int) (hue / 60); // color quadrant 0..2555 + double f = hue % 60; // 0..59 + double q = 255 - ((f / 60) * sat255); + + double p = 0; + double t = 255 - (((60 - f) / 60) * 255); + + switch (i) { + case 0: + // redD = 255; + greenD = t; + blueD = p; + break; + case 1: + redD = q; + // greenD = 255; + blueD = p; + break; + case 2: + redD = p; + // greenD = 255; + blueD = t; + break; + case 3: + redD = p; + greenD = q; + // blueD = 255; + break; + case 4: + redD = t; + greenD = p; + // blueD = 255; + break; + default: + // redD = 255; + greenD = p; + blueD = q; + break; + } + } + + logger.debug("Colors from hue, assuming full brightness R: {} G: {} B: {}", redD, greenD, blueD); + + // Convert the "PercentType" to a percent + double saturationPercent = (hsb.getSaturation().doubleValue() / 100); + + // Calculate the white intensity from saturation and adjust down the other colors + // This is approximately what the WiZ app does. Personally, I think it undersaturates everything + if (saturationPercent < 0.5) { + // At less than 50% saturation, maximize white and lower the other intensities by 2x of the saturation + // percent. (2x to give us full range between 0-50%) + // white = 255; + // ^^ WiZ does this.. I think it's very undersaturated that way + white = 255 / 2; // Divide by two to not undersaturate + red = (int) (redD * (2 * saturationPercent)); + green = (int) (greenD * (2 * saturationPercent)); + blue = (int) (blueD * (2 * saturationPercent)); + } else { + // At >50% saturation, colors are at full and increase saturation by decreasing the white intensity. + // white = (int) (255 * 2 * (1 - saturationPercent)); + // ^^ WiZ does this.. I think it's very undersaturated that way + white = (int) ((255 / 2) * 2 * (1 - saturationPercent)); + red = (int) redD; + green = (int) greenD; + blue = (int) blueD; + } + + // Note: We're keeping the brightness in a totally separate channel + return new int[] { red, green, blue, white }; + } + + /** + * Converts Red/Green/Blue/White components to Hue and saturation. + * + * @param int red - the value of the red component (0-255) + * @param int green - the value of the green component (0-255) + * @param int blue - the value of the blue component (0-255) + * @param int white - the value of the white component (0-255) + * + * Totally made this up. + * + * @return a {@link ColorRequestParam} with the color components + */ + public HSBType rgbwDimmingToHSB(int red, int green, int blue, int white, int dimming) { + // Can get hue from the ratios of the colors. + // The calculated *hue* component of the HSB should be correct regardless of the + // state of the white lights because it's strictly based on the ratio of the colors + DecimalType hue = HSBType.fromRGB(red, green, blue).getHue(); + double saturationPercent; + if (white < 255) { + saturationPercent = (int) (1 - (white / (255 * 2))); + } else { + saturationPercent = Math.max(red, Math.max(green, blue)) / (255 * 2); + } + HSBType out = new HSBType(hue, new PercentType((int) saturationPercent * 100), new PercentType(dimming)); + return out; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java new file mode 100644 index 0000000000000..edc4ca98c0142 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java @@ -0,0 +1,92 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.utils; + +import static java.nio.charset.StandardCharsets.*; + +import java.net.DatagramPacket; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.entities.WizLightingRequest; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonParseException; + +/** + * Transforms the datagram packet to request/response + * + * @author Sriram Balakrishnan - Initial contribution + * + */ +@NonNullByDefault +public class WizLightingPacketConverter { + + private final Logger logger = LoggerFactory.getLogger(WizLightingPacketConverter.class); + + private Gson wizlightingGsonBuilder; + + /** + * Default constructor of the packet converter. + */ + public WizLightingPacketConverter() { + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(WizLightingResponse.class, new WizResponseDeserializer()); + gsonBuilder.excludeFieldsWithoutExposeAnnotation(); + // gsonBuilder.setLenient(); + Gson gson = gsonBuilder.create(); + this.wizlightingGsonBuilder = gson; + } + + /** + * Method that transforms one {@link WizLightingRequest} to json requst + * + * @param requestPacket the {@link WizLightingRequest}. + * @return the byte array with the message. + */ + public byte[] transformToByteMessage(final WizLightingRequest requestPacket) { + byte[] requestDatagram = null; + + // {"id":20,"method":"setPilot","params":{"sceneId":18}} + String jsonCmd = this.wizlightingGsonBuilder.toJson(requestPacket); + + requestDatagram = jsonCmd.getBytes(UTF_8); + return requestDatagram; + } + + /** + * Method that transforms {@link DatagramPacket} to a + * {@link WizLightingResponse} Object + * + * @param packet the {@link DatagramPacket} + * @return the {@link WizLightingResponse} + */ + public @Nullable WizLightingResponse transformResponsePacket(final DatagramPacket packet) { + String responseJson = new String(packet.getData(), 0, packet.getLength(), UTF_8); + logger.debug("Incoming packet from {} to convert -> {}", packet.getAddress().getHostAddress(), responseJson); + + @Nullable + WizLightingResponse response = null; + try { + response = this.wizlightingGsonBuilder.fromJson(responseJson, WizLightingResponse.class); + response.setWizResponseIpAddress(packet.getAddress().getHostAddress()); + } catch (JsonParseException e) { + logger.error("Error parsing json! {}", e.getMessage()); + } + return response; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java new file mode 100644 index 0000000000000..2100eab222899 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java @@ -0,0 +1,221 @@ +/** + * 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wizlighting.internal.utils; + +import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; + +import java.lang.reflect.Type; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wizlighting.internal.entities.ErrorResponseResult; +import org.openhab.binding.wizlighting.internal.entities.SystemConfigResult; +import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wizlighting.internal.entities.WizLightingSyncState; +import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + +/** + * Deserializes incoming json + * + * @author Sara Geleskie Damiano - Initial contribution + * + */ + +@NonNullByDefault +public class WizResponseDeserializer implements JsonDeserializer { + // We can't do too much logging, can we? + private final Logger logger = LoggerFactory.getLogger(WizResponseDeserializer.class); + + @Override + @Nullable + public WizLightingResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOfT, + @Nullable JsonDeserializationContext context) throws JsonParseException { + // The outgoing response + WizLightingResponse deserializedResponse = new WizLightingResponse(); + + // The incoming JSON + JsonObject jobject; + if (json == null) { + logger.trace("No json provided to parse."); + } else if (context == null) { + logger.trace("No context available for parsing sub-objects."); + } else { + jobject = json.getAsJsonObject(); + + // Parse the ID + if (jobject.has("id")) { + deserializedResponse.setId(jobject.get("id").getAsInt()); + } + // Parse the environment - I think this is always sent, but I'm checking anyway + if (jobject.has("env")) { + deserializedResponse.setEnv(jobject.get("env").getAsString()); + } + + // Check if the response contains an error + // Return without completing parsing if there's an error + if (jobject.has("error")) { + ErrorResponseResult error = context.deserialize(jobject.getAsJsonObject("error"), + ErrorResponseResult.class); + deserializedResponse.setError(error); + if (jobject.has("method")) { + logger.warn("Bulb returned an error on method {}: {}, {}", jobject.get("method"), error.code, + error.message); + } else { + logger.warn("Bulb returned an error: {}", error.code); + } + return deserializedResponse; + } + + // Parse the method. We will use the method to decide how to continue to parse + // Bail out of everything if we cannot understand the method. + WizLightingMethodType method; + if (jobject.has("method")) { + try { + String inMethod = jobject.get("method").getAsString(); + String properCaseMethod = inMethod.substring(0, 1).toUpperCase() + inMethod.substring(1); + method = WizLightingMethodType.valueOf(properCaseMethod); + deserializedResponse.setMethod(method); + } catch (IllegalArgumentException e) { + logger.warn("Bulb returned an invalid method: {}", jobject.get("method")); + return deserializedResponse; + } + } else { + throw new JsonParseException("Incoming message did not contain a method and cannot be parsed!"); + } + + switch (method) { + case Registration: + // {"method": "registration", "id": 1, "env": "pro", "result": {"mac": + // "macOfopenHAB", "success": true}} + if (!jobject.has("result")) { + throw new JsonParseException("registration received, but no result object present"); + } + JsonObject registrationResult = jobject.getAsJsonObject("result"); + if (!registrationResult.has("mac")) { + throw new JsonParseException("registration received, but no MAC address present"); + } + String mac = registrationResult.get("mac").getAsString(); + deserializedResponse.setWizResponseMacAddress(mac); + deserializedResponse.setResultSucess(registrationResult.get("success").getAsBoolean()); + logger.trace("Registration result deserialized with mac {} and success {}", mac, + registrationResult.get("success").getAsBoolean()); + break; + + case Pulse: + // {"method":"pulse","id":22,"env":"pro","result":{"success":true}} + case SetPilot: + // {"method":"setPilot","id":24,"env":"pro","result":{"success":true}} + if (!jobject.has("result")) { + throw new JsonParseException("pulse or setPilot method received, but no result object present"); + } + JsonObject setResult = jobject.getAsJsonObject("result"); + deserializedResponse.setResultSucess(setResult.get("success").getAsBoolean()); + logger.trace("Result deserialized - command success {}", setResult.get("success").getAsBoolean()); + break; + + case FirstBeat: + // {"method": "firstBeat", "id": 0, "env": "pro", "params": {"mac": "theBulbMacAddress", + // "homeId": xxxxxx, "fwVersion": "1.15.2"}} + if (!jobject.has("params")) { + throw new JsonParseException("firstBeat received, but no params object present"); + } + SystemConfigResult parsedFBParams = context.deserialize(jobject.getAsJsonObject("params"), + SystemConfigResult.class); + if (parsedFBParams.mac == MISSING_INVALID_MAC_ADDRESS) { + throw new JsonParseException("firstBeat received, but no MAC address present"); + } + deserializedResponse.setWizResponseMacAddress(parsedFBParams.mac); + deserializedResponse.setResultSucess(true); + deserializedResponse.setSystemConfigResult(parsedFBParams); + logger.trace("firstBeat result deserialized with mac {}", parsedFBParams.mac); + break; + + case GetSystemConfig: + // {"method": "getSystemConfig", "id": 22, "env": "pro", + // "result": {"mac": "theBulbMacAddress", "homeId": xxxxxx, "roomId": xxxxxx, + // "homeLock": false, "pairingLock": false, "typeId": 0, "moduleName": + // "ESP01_SHRGB1C_31", "fwVersion": "1.15.2", "groupId": 0, "drvConf":[33,1]}} + if (!jobject.has("result")) { + throw new JsonParseException("getSystemConfig received, but no result object present"); + } + SystemConfigResult parsedCResult = context.deserialize(jobject.getAsJsonObject("result"), + SystemConfigResult.class); + if (parsedCResult.mac == MISSING_INVALID_MAC_ADDRESS) { + throw new JsonParseException("getSystemConfig received, but no MAC address present"); + } + deserializedResponse.setWizResponseMacAddress(parsedCResult.mac); + deserializedResponse.setResultSucess(true); + deserializedResponse.setSystemConfigResult(parsedCResult); + logger.trace("systemConfig result deserialized with mac {}", parsedCResult.mac); + break; + + case GetPilot: + // {"method": "getPilot", "id": 22, "env": "pro", "result": {"mac": + // "theBulbMacAddress", "rssi":-76, "state": true, "sceneId": 0, "temp": 2700, + // "dimming": 42, "schdPsetId": 5}} + if (!jobject.has("result")) { + throw new JsonParseException("getPilot received, but no result object present"); + } + WizLightingSyncState parsedPResult = context.deserialize(jobject.getAsJsonObject("result"), + WizLightingSyncState.class); + if (parsedPResult.mac == MISSING_INVALID_MAC_ADDRESS) { + throw new JsonParseException("getPilot received, but no MAC address present"); + } + deserializedResponse.setWizResponseMacAddress(parsedPResult.mac); + deserializedResponse.setResultSucess(true); + deserializedResponse.setSyncParams(parsedPResult); + logger.trace("getPilot result deserialized with mac {}", parsedPResult.mac); + break; + + case SyncPilot: + // {"method": "syncPilot", "id": 219, "env": "pro", "params": { "mac": + // "theBulbMacAddress", "rssi": -72, "src": "hb", "mqttCd": 0, "state": true, "sceneId": + // 0, "temp": 3362, "dimming": 69, "schdPsetId": 5}} + if (!jobject.has("params")) { + throw new JsonParseException("syncPilot received, but no params object present"); + } + WizLightingSyncState parsedPParam = context.deserialize(jobject.getAsJsonObject("params"), + WizLightingSyncState.class); + if (parsedPParam.mac == MISSING_INVALID_MAC_ADDRESS) { + throw new JsonParseException("syncPilot received, but no MAC address present"); + } + deserializedResponse.setWizResponseMacAddress(parsedPParam.mac); + deserializedResponse.setResultSucess(true); + deserializedResponse.setSyncParams(parsedPParam); + logger.trace("syncPilot result deserialized with mac {}", parsedPParam.mac); + break; + + case SetSystemConfig: + // ?? I'm not trying this at home! + case SetWifiConfig: + // ?? I'm not trying this at home! + case GetWifiConfig: + // The returns an encrypted string and I'm not using it so I'm not bothering to parse it + // {"method":"getWifiConfig","id":22,"env":"pro","result":{:["longStringInEncryptedUnicode"]}} + case UnknownMethod: + // This should just never happen + break; + } + } + + return deserializedResponse; + } +} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 0000000000000..3f473e986eef7 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + WiZ Lighting Binding + Binding for WiZ Lighting smart bulbs. + local + + diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/config/config.xml new file mode 100644 index 0000000000000..4873139d8d68b --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/config/config.xml @@ -0,0 +1,41 @@ + + + + + + + MAC address of the bulb + true + + + + network-address + IP address of the bulb + true + + + + Update time interval in seconds to request the status of the bulb while it is connected to the network. + 60 + true + + + + True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. + true + false + + + + Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status + queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to + immediately detect it. This is only as a back-up to re-find the bulb. + 15 + true + + + + diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties new file mode 100644 index 0000000000000..9238ab0a83761 --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties @@ -0,0 +1,72 @@ +# add-on + +addon.wizlighting.name = WiZ Lighting Binding +addon.wizlighting.description = Binding for WiZ Lighting smart bulbs. + +# thing types + +thing-type.wizlighting.ceiling-fan.label = WiZ Ceiling Fan +thing-type.wizlighting.ceiling-fan.description = Supports WiZ Ceiling Fans +thing-type.wizlighting.color-bulb.label = WiZ Color Bulb +thing-type.wizlighting.color-bulb.description = Supports WiZ Full Color with Tunable White Bulbs +thing-type.wizlighting.dimmable-bulb.label = WiZ Dimmable Bulb +thing-type.wizlighting.dimmable-bulb.description = Supports WiZ Single Color Dimmable Bulbs +thing-type.wizlighting.plug.label = WiZ Smart Plug +thing-type.wizlighting.plug.description = Supports WiZ Smart Plugs +thing-type.wizlighting.tunable-bulb.label = WiZ Tunable Bulb +thing-type.wizlighting.tunable-bulb.description = Supports WiZ Tunable White Bulbs + +# thing types config + +thing-type.config.wiz.light.bulbIpAddress.label = Bulb IP Address +thing-type.config.wiz.light.bulbIpAddress.description = IP address of the bulb +thing-type.config.wiz.light.bulbMacAddress.label = Bulb MAC Address +thing-type.config.wiz.light.bulbMacAddress.description = MAC address of the bulb +thing-type.config.wiz.light.reconnectInterval.label = Reconnect Interval +thing-type.config.wiz.light.reconnectInterval.description = Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. +thing-type.config.wiz.light.updateInterval.label = Update Interval +thing-type.config.wiz.light.updateInterval.description = Update time interval in seconds to request the status of the bulb while it is connected to the network. +thing-type.config.wiz.light.useHeartBeats.label = Use Heartbeats +thing-type.config.wiz.light.useHeartBeats.description = True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. + +# channel types + +channel-type.wizlighting.color-temperature-abs.label = Color Temperature +channel-type.wizlighting.color-temperature-abs.description = Controls the color temperature of the light in Kelvin +channel-type.wizlighting.last-update.label = Last Update +channel-type.wizlighting.last-update.description = Timestamp of last status update +channel-type.wizlighting.light-mode.label = Light Mode +channel-type.wizlighting.light-mode.state.option.1 = Ocean +channel-type.wizlighting.light-mode.state.option.2 = Romance +channel-type.wizlighting.light-mode.state.option.3 = Sunset +channel-type.wizlighting.light-mode.state.option.4 = Party +channel-type.wizlighting.light-mode.state.option.5 = Fireplace +channel-type.wizlighting.light-mode.state.option.6 = Cozy White +channel-type.wizlighting.light-mode.state.option.7 = Forest +channel-type.wizlighting.light-mode.state.option.8 = Pastel Colors +channel-type.wizlighting.light-mode.state.option.9 = Wakeup +channel-type.wizlighting.light-mode.state.option.10 = Bed Time +channel-type.wizlighting.light-mode.state.option.11 = Warm White +channel-type.wizlighting.light-mode.state.option.12 = Daylight +channel-type.wizlighting.light-mode.state.option.13 = Cool White +channel-type.wizlighting.light-mode.state.option.14 = Night Light +channel-type.wizlighting.light-mode.state.option.15 = Focus +channel-type.wizlighting.light-mode.state.option.16 = Relax +channel-type.wizlighting.light-mode.state.option.17 = True Colors +channel-type.wizlighting.light-mode.state.option.18 = TV Time +channel-type.wizlighting.light-mode.state.option.19 = Plant Growth +channel-type.wizlighting.light-mode.state.option.20 = Spring +channel-type.wizlighting.light-mode.state.option.21 = Summer +channel-type.wizlighting.light-mode.state.option.22 = Fall +channel-type.wizlighting.light-mode.state.option.23 = Deep Dive +channel-type.wizlighting.light-mode.state.option.24 = Jungle +channel-type.wizlighting.light-mode.state.option.25 = Mojito +channel-type.wizlighting.light-mode.state.option.26 = Club +channel-type.wizlighting.light-mode.state.option.27 = Christmas +channel-type.wizlighting.light-mode.state.option.28 = Halloween +channel-type.wizlighting.light-mode.state.option.29 = Candlelight +channel-type.wizlighting.light-mode.state.option.30 = Golden White +channel-type.wizlighting.light-mode.state.option.31 = Pulse +channel-type.wizlighting.light-mode.state.option.32 = Steampunk +channel-type.wizlighting.speed.label = Dynamic Light Mode Speed +channel-type.wizlighting.speed.description = Speed of color/intensity changes in dynamic light modes diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..f7e3627ec1b6a --- /dev/null +++ b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,153 @@ + + + + + + + Supports WiZ Full Color with Tunable White Bulbs + + + + + + + + + + + + + + + + + Supports WiZ Tunable White Bulbs + + + + + + + + + + + + + + + + + Supports WiZ Single Color Dimmable Bulbs + + + + + + + + + + + + + + + Supports WiZ Smart Plugs + + + + + + + + + + + + + Supports WiZ Ceiling Fans + + + + + + + + + + String + + + Lighting + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Dimmer + + Speed of color/intensity changes in dynamic light modes + + Lighting + + + + + DateTime + + Timestamp of last status update + + + + + Number:Temperature + + Controls the color temperature of the light in Kelvin + ColorLight + + Control + ColorTemperature + + + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index df87fecff2612..91cf7b66d0c8e 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -454,6 +454,7 @@ org.openhab.binding.wemo org.openhab.binding.wifiled org.openhab.binding.windcentrale + org.openhab.binding.wizlighting org.openhab.binding.wlanthermo org.openhab.binding.wled org.openhab.binding.wolfsmartset From f097a6f37a34d87ba62626443ff0036f9aef1117 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 31 Oct 2024 15:45:46 -0600 Subject: [PATCH 02/26] update copyright year Signed-off-by: Cody Cutrer --- .../wizlighting/internal/WizLightingBindingConstants.java | 2 +- .../binding/wizlighting/internal/WizLightingHandlerFactory.java | 2 +- .../internal/config/WizLightingDeviceConfiguration.java | 2 +- .../internal/discovery/WizLightingDiscoveryService.java | 2 +- .../wizlighting/internal/entities/ColorRequestParam.java | 2 +- .../internal/entities/ColorTemperatureRequestParam.java | 2 +- .../wizlighting/internal/entities/DimmingRequestParam.java | 2 +- .../wizlighting/internal/entities/ErrorResponseResult.java | 2 +- .../wizlighting/internal/entities/FanStateRequestParam.java | 2 +- .../wizlighting/internal/entities/FirstBeatResponseParam.java | 2 +- .../openhab/binding/wizlighting/internal/entities/Param.java | 2 +- .../wizlighting/internal/entities/PulseRequestParam.java | 2 +- .../wizlighting/internal/entities/RegistrationRequestParam.java | 2 +- .../wizlighting/internal/entities/SceneRequestParam.java | 2 +- .../wizlighting/internal/entities/SpeedRequestParam.java | 2 +- .../wizlighting/internal/entities/StateRequestParam.java | 2 +- .../wizlighting/internal/entities/SystemConfigResult.java | 2 +- .../wizlighting/internal/entities/WizLightingRequest.java | 2 +- .../wizlighting/internal/entities/WizLightingResponse.java | 2 +- .../wizlighting/internal/entities/WizLightingSyncState.java | 2 +- .../wizlighting/internal/enums/WizLightingColorMode.java | 2 +- .../wizlighting/internal/enums/WizLightingLightMode.java | 2 +- .../wizlighting/internal/enums/WizLightingMethodType.java | 2 +- .../wizlighting/internal/enums/WizLightingModuleType.java | 2 +- .../wizlighting/internal/handler/WizLightingHandler.java | 2 +- .../wizlighting/internal/handler/WizLightingMediator.java | 2 +- .../wizlighting/internal/handler/WizLightingMediatorImpl.java | 2 +- .../internal/runnable/WizLightingUpdateReceiverRunnable.java | 2 +- .../binding/wizlighting/internal/utils/ValidationUtils.java | 2 +- .../binding/wizlighting/internal/utils/WizColorConverter.java | 2 +- .../wizlighting/internal/utils/WizLightingPacketConverter.java | 2 +- .../wizlighting/internal/utils/WizResponseDeserializer.java | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java index 06d7f0e80b068..f2c7f803c0d5e 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java index 15287cae816d1..725d733a6ff31 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java index 84e4024addebe..b673ab4e7799d 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java index 8a7be7239efd6..0e8f96608e52d 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java index bed1c7ead3fe4..7104c9f7423c8 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java index bcb0fd6e446ea..b95d20e4b6bfd 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java index 52fb07ce9d1e4..e39c71a66ab13 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java index d186dd5cf29a5..657d773920fa6 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java index 77e168cac4874..11624960ee01b 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java index be05f4e7a7067..477fbab65b99b 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java index 1398cd075492b..c90db1756ecf9 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java index ff1ffac1eed10..a6b1f878040ef 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java index 03e167957f33d..d27276a6440ce 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java index 3244509b2d3cb..7bc94e4ecdffa 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java index 0eecacca33b8b..21cafa5730b07 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java index e91d4b3fda457..6f7185e6f2210 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java index c50e7787b9498..29c3f2e981303 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java index 97ecc13a0b2c0..ece85d8e93f32 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java index 16fad513e011e..12b736333860e 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java index b4ebf4b1d32b1..501f5ec0eb7ee 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java index ee6816b079c26..181a49349c6da 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java index 1592fdeeb2bd1..8c4097759d70e 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java index e1cc8294777e5..848ee2933cbec 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java index 67d86400366fb..9dcc0b2928d4e 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java index e2a6a771347c1..9170c38d847ed 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java index 33223ea669543..8da2da71257ea 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java index 820d8b90a0365..dba9de48e74e8 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java index 2c21162202bcc..16dd066f1b165 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java index 27b9a08bab943..9a070260bc592 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java index 1ffbac11481db..365eeec34a082 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java index edc4ca98c0142..5f65cb563c4b0 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java index 2100eab222899..e3e430c077a6e 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. From faa68eb7d22e6ee55fca145ba410a23a7074c9f7 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 31 Oct 2024 15:58:41 -0600 Subject: [PATCH 03/26] address SAT warnings and errors Signed-off-by: Cody Cutrer --- bundles/org.openhab.binding.wizlighting/README.md | 3 +++ .../internal/entities/FanStateRequestParam.java | 2 ++ .../wizlighting/internal/enums/WizLightingColorMode.java | 3 +++ .../wizlighting/internal/enums/WizLightingLightMode.java | 8 ++++++-- .../wizlighting/internal/enums/WizLightingMethodType.java | 3 +++ .../wizlighting/internal/enums/WizLightingModuleType.java | 5 ++++- .../wizlighting/internal/handler/WizLightingHandler.java | 6 +++--- .../binding/wizlighting/internal/utils/NetworkUtils.java | 8 ++++++-- 8 files changed, 30 insertions(+), 8 deletions(-) diff --git a/bundles/org.openhab.binding.wizlighting/README.md b/bundles/org.openhab.binding.wizlighting/README.md index a786527fc5582..7c1857591d0e7 100644 --- a/bundles/org.openhab.binding.wizlighting/README.md +++ b/bundles/org.openhab.binding.wizlighting/README.md @@ -17,6 +17,7 @@ Local control must also be enabled with-in the WiZ app in the app settings. (This is the default.) ## Supported Things + * WiZ Full Color with Tunable White Bulbs * WiZ Tunable White Bulbs * WiZ Dimmable single-color bulbs @@ -25,6 +26,7 @@ Local control must also be enabled with-in the WiZ app in the app settings. _Note_ This binding was created for and tested on the full color with tunable white bulbs, however, users have reported success with other bulb types and plugs. ## Discovery + New devices can be discovered by scanning and may also be discovered by background discovery. All discovered devices will default to 'Full Color' bulbs if unable to automatically detect the specific device type. You may need to create devices manually if desired. @@ -121,6 +123,7 @@ The Binding supports the following Light Modes | 32 | Steampunk | ## Bulb Limitations + - Full-color bulbs operate in either color mode OR tunable white/color temperature mode. The RGB LED's are NOT used to control temperature - separate warm and cool white LED's are used. Sending a command on the color channel or the temperature channel will cause the bulb to switch the relevant mode. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java index 11624960ee01b..87ed4958e366f 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java @@ -18,6 +18,8 @@ /** * This POJO represents Fan State Request Param + * + * @author Stefan Fussenegger - Initial Contribution */ @NonNullByDefault public class FanStateRequestParam implements Param { diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java index 181a49349c6da..2189272e1ee3d 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.wizlighting.internal.enums; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * This enum represents the possible color modes for WiZ bulbs. * The bulbs come in three types - full color with tunable white, @@ -22,6 +24,7 @@ * @author Sara Geleskie Damiano - Initial contribution * */ +@NonNullByDefault public enum WizLightingColorMode { // Full color mode RGBMode("Full Color"), diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java index 8c4097759d70e..cfd6e6052213e 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java @@ -15,12 +15,16 @@ import java.util.HashMap; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * This enum represents the possible scene modes. * * @author Sara Geleskie Damiano - Initial contribution * */ +@NonNullByDefault public enum WizLightingLightMode { Ocean("Ocean", 1), Romance("Romance", 2), @@ -89,7 +93,7 @@ public int getSceneId() { } } - public static WizLightingLightMode fromSceneId(int id) { + public static @Nullable WizLightingLightMode fromSceneId(int id) { WizLightingLightMode r = null; if (id > 0 && id < 33) { r = LIGHT_MODE_MAP_BY_ID.get(id); @@ -97,7 +101,7 @@ public static WizLightingLightMode fromSceneId(int id) { return r; } - public static WizLightingLightMode fromSceneName(String name) { + public static @Nullable WizLightingLightMode fromSceneName(String name) { WizLightingLightMode r = null; if (name != null && !"".equals(name)) { r = LIGHT_MODE_MAP_BY_NAME.get(name.toLowerCase().replaceAll("\\W+", "")); diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java index 848ee2933cbec..6c2e00843a954 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.wizlighting.internal.enums; +import org.eclipse.jdt.annotation.NonNullByDefault; + import com.google.gson.annotations.SerializedName; /** @@ -20,6 +22,7 @@ * @author Sriram Balakrishnan - Initial contribution * */ +@NonNullByDefault public enum WizLightingMethodType { /** * Registration - used to "register" with the bulb: This notifies the bult that diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java index 9dcc0b2928d4e..e77ac8a6e47bb 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java @@ -17,6 +17,8 @@ import java.util.HashMap; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.thing.ThingTypeUID; /** @@ -25,6 +27,7 @@ * @author Sara Geleskie Damiano - Initial contribution * */ +@NonNullByDefault public enum WizLightingModuleType { FullColorWifi("ESP01_SHRGB1C_31", THING_TYPE_COLOR_BULB), TunableWhiteWifi("ESP56_SHTW3_01", THING_TYPE_TUNABLE_BULB), @@ -56,7 +59,7 @@ public String getModuleName() { } } - public static ThingTypeUID getThingTypeUIDFromModuleName(String moduleName) { + public static @Nullable ThingTypeUID getThingTypeUIDFromModuleName(String moduleName) { return MODULE_NAME_MAP.get(moduleName); } } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java index 9170c38d847ed..dc497933758df 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java @@ -238,7 +238,7 @@ private void handleLightModeCommand(Command command) { mostRecentState.sceneId = commandAsLightMode.getSceneId(); setPilotCommand(new SceneRequestParam(commandAsLightMode.getSceneId())); } else { - logger.warn("[{}] Command [{}] not a recognized Light Mode!", config.bulbIpAddress); + logger.warn("[{}] Command [{}] not a recognized Light Mode!", config.bulbIpAddress, command); } } @@ -455,8 +455,8 @@ public synchronized void newReceivedResponseMessage(final WizLightingResponse re // Check if the bulb still has the same IP address it had previously // If not, we need to update the configuration for the thing. - if (receivedMessage.getWizResponseIpAddress() != MISSING_INVALID_IP_ADDRESS - && receivedMessage.getWizResponseIpAddress() != this.getBulbIpAddress()) { + if (!receivedMessage.getWizResponseIpAddress().equals(MISSING_INVALID_IP_ADDRESS) + && !receivedMessage.getWizResponseIpAddress().equals(this.getBulbIpAddress())) { // get the old config Configuration priorConfig = getConfig(); // change the ip address property diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java index ee641e4e517b8..29c44d92725e5 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java +++ b/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2020 Contributors to the openHAB project + * Copyright (c) 2010-2024 Contributors to the openHAB project * * See the NOTICE file(s) distributed with this work for additional * information. @@ -18,6 +18,9 @@ import java.rmi.UnknownHostException; import java.util.Enumeration; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * Utility class to perform some network routines. * @@ -25,6 +28,7 @@ * @author Joshua Freeman - Modified to get MAC matching IP * */ +@NonNullByDefault public final class NetworkUtils { /** * Returns the MAC address of the openHAB first network device. @@ -33,7 +37,7 @@ public final class NetworkUtils { * @throws UnknownHostException * @throws SocketException */ - public static String getMyMacAddress(String matchIP) throws UnknownHostException, SocketException { + public static @Nullable String getMyMacAddress(String matchIP) throws UnknownHostException, SocketException { String macAddress = null; Enumeration networks = NetworkInterface.getNetworkInterfaces(); while (networks.hasMoreElements()) { From aa262a2e0f48603e3729bdfc6eb8fa6db2c550fb Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 1 Nov 2024 10:47:54 -0600 Subject: [PATCH 04/26] rename to just wiz including renaming files and packages Signed-off-by: Cody Cutrer --- CODEOWNERS | 2 +- bom/openhab-addons/pom.xml | 2 +- .../NOTICE | 0 .../README.md | 4 +- .../pom.xml | 4 +- .../src/main/feature/feature.xml | 6 +- .../wiz/internal/WizBindingConstants.java} | 8 +- .../wiz/internal/WizHandlerFactory.java} | 24 ++-- .../config/WizDeviceConfiguration.java} | 6 +- .../discovery/WizDiscoveryService.java} | 47 ++++---- .../internal/entities/ColorRequestParam.java | 4 +- .../ColorTemperatureRequestParam.java | 4 +- .../entities/DimmingRequestParam.java | 2 +- .../entities/ErrorResponseResult.java | 4 +- .../entities/FanStateRequestParam.java | 2 +- .../entities/FirstBeatResponseParam.java | 4 +- .../binding/wiz}/internal/entities/Param.java | 2 +- .../internal/entities/PulseRequestParam.java | 2 +- .../entities/RegistrationRequestParam.java | 2 +- .../internal/entities/SceneRequestParam.java | 2 +- .../internal/entities/SpeedRequestParam.java | 2 +- .../internal/entities/StateRequestParam.java | 2 +- .../internal/entities/SystemConfigResult.java | 4 +- .../wiz/internal/entities/WizRequest.java} | 18 +-- .../wiz/internal/entities/WizResponse.java} | 22 ++-- .../wiz/internal/entities/WizSyncState.java} | 22 ++-- .../wiz/internal/enums/WizColorMode.java} | 6 +- .../wiz/internal/enums/WizLightMode.java} | 24 ++-- .../wiz/internal/enums/WizMethodType.java} | 8 +- .../wiz/internal/enums/WizModuleType.java} | 10 +- .../wiz/internal/handler/WizHandler.java} | 105 +++++++++--------- .../wiz/internal/handler/WizMediator.java} | 28 ++--- .../internal/handler/WizMediatorImpl.java} | 79 +++++++------ .../runnable/WizUpdateReceiverRunnable.java} | 27 +++-- .../wiz}/internal/utils/NetworkUtils.java | 2 +- .../wiz}/internal/utils/ValidationUtils.java | 2 +- .../internal/utils/WizColorConverter.java | 2 +- .../internal/utils/WizPacketConverter.java} | 36 +++--- .../utils/WizResponseDeserializer.java | 32 +++--- .../src/main/resources/OH-INF/addon/addon.xml | 6 +- .../main/resources/OH-INF/config/config.xml | 0 .../main/resources/OH-INF/i18n/wiz.properties | 72 ++++++++++++ .../resources/OH-INF/thing/thing-types.xml | 3 +- .../OH-INF/i18n/wizlighting.properties | 72 ------------ bundles/pom.xml | 2 +- 45 files changed, 356 insertions(+), 361 deletions(-) rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/NOTICE (100%) rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/README.md (98%) rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/pom.xml (79%) rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/src/main/feature/feature.xml (51%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java} (95%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java} (67%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java} (84%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java} (85%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/ColorRequestParam.java (94%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/ColorTemperatureRequestParam.java (90%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/DimmingRequestParam.java (95%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/ErrorResponseResult.java (87%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/FanStateRequestParam.java (94%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/FirstBeatResponseParam.java (89%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/Param.java (91%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/PulseRequestParam.java (95%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/RegistrationRequestParam.java (97%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/SceneRequestParam.java (94%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/SpeedRequestParam.java (95%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/StateRequestParam.java (94%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/entities/SystemConfigResult.java (94%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java} (73%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java} (84%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java} (88%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizColorMode.java} (89%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java} (75%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java} (95%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizModuleType.java} (82%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java} (87%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java} (66%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java} (70%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java} (81%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/utils/NetworkUtils.java (97%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/utils/ValidationUtils.java (96%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/utils/WizColorConverter.java (99%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java} (62%) rename bundles/{org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting => org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz}/internal/utils/WizResponseDeserializer.java (89%) rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/src/main/resources/OH-INF/addon/addon.xml (59%) rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/src/main/resources/OH-INF/config/config.xml (100%) create mode 100644 bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties rename bundles/{org.openhab.binding.wizlighting => org.openhab.binding.wiz}/src/main/resources/OH-INF/thing/thing-types.xml (98%) delete mode 100644 bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties diff --git a/CODEOWNERS b/CODEOWNERS index e202848ab41eb..0526f553154f3 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -421,7 +421,7 @@ /bundles/org.openhab.binding.wemo/ @hmerk @jlaur /bundles/org.openhab.binding.wifiled/ @openhab/add-ons-maintainers /bundles/org.openhab.binding.windcentrale/ @marcelrv @wborn -/bundles/org.openhab.binding.wizlighting/ @ccutrer @frejos +/bundles/org.openhab.binding.wiz/ @ccutrer @frejos /bundles/org.openhab.binding.wlanthermo/ @CSchlipp /bundles/org.openhab.binding.wled/ @Skinah /bundles/org.openhab.binding.wolfsmartset/ @BoBiene diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index cafcb0e4f1c2d..a546e9c9cbed4 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -2083,7 +2083,7 @@ org.openhab.addons.bundles - org.openhab.binding.wizlighting + org.openhab.binding.wiz ${project.version} diff --git a/bundles/org.openhab.binding.wizlighting/NOTICE b/bundles/org.openhab.binding.wiz/NOTICE similarity index 100% rename from bundles/org.openhab.binding.wizlighting/NOTICE rename to bundles/org.openhab.binding.wiz/NOTICE diff --git a/bundles/org.openhab.binding.wizlighting/README.md b/bundles/org.openhab.binding.wiz/README.md similarity index 98% rename from bundles/org.openhab.binding.wizlighting/README.md rename to bundles/org.openhab.binding.wiz/README.md index 7c1857591d0e7..1c875457bb05f 100644 --- a/bundles/org.openhab.binding.wizlighting/README.md +++ b/bundles/org.openhab.binding.wiz/README.md @@ -64,7 +64,7 @@ Thing parameters: Example Thing: ``` -Thing wizlighting:bulb:lamp "My Lamp" @ "Living Room" [ macAddress="accf23343cxx", ipAddress="192.168.0.xx" ] +Thing wiz:bulb:lamp "My Lamp" @ "Living Room" [ macAddress="accf23343cxx", ipAddress="192.168.0.xx" ] ``` ## Channels @@ -137,5 +137,5 @@ Sending a command on the color channel or the temperature channel will cause the ## Example item linked to a channel ``` -Color LivingRoom_Light_Color "Living Room Lamp" (gLivingroom) {channel="wizlighting:color-bulb:accf23343cxx:color"} +Color LivingRoom_Light_Color "Living Room Lamp" (gLivingroom) {channel="wiz:color-bulb:accf23343cxx:color"} ``` diff --git a/bundles/org.openhab.binding.wizlighting/pom.xml b/bundles/org.openhab.binding.wiz/pom.xml similarity index 79% rename from bundles/org.openhab.binding.wizlighting/pom.xml rename to bundles/org.openhab.binding.wiz/pom.xml index a049f1b4145e3..f1940b89af96c 100644 --- a/bundles/org.openhab.binding.wizlighting/pom.xml +++ b/bundles/org.openhab.binding.wiz/pom.xml @@ -10,8 +10,8 @@ 4.3.0-SNAPSHOT - org.openhab.binding.wizlighting + org.openhab.binding.wiz - openHAB Add-ons :: Bundles :: WiZ Lighting Binding + openHAB Add-ons :: Bundles :: WiZ Binding diff --git a/bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml b/bundles/org.openhab.binding.wiz/src/main/feature/feature.xml similarity index 51% rename from bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml rename to bundles/org.openhab.binding.wiz/src/main/feature/feature.xml index 334b646b4c816..7f4ccfbea2b4c 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.wiz/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - + openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.wizlighting/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.wiz/${project.version} diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java similarity index 95% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index f2c7f803c0d5e..f0879162260d6 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal; +package org.openhab.binding.wiz.internal; import java.util.Set; import java.util.stream.Collectors; @@ -20,19 +20,19 @@ import org.openhab.core.thing.ThingTypeUID; /** - * The {@link WizLightingBindingConstants} class defines common constants, which + * The {@link WizBindingConstants} class defines common constants, which * are used across the whole binding. * * @author Sriram Balakrishnan - Initial contribution * @author Joshua Freeman - update version */ @NonNullByDefault -public class WizLightingBindingConstants { +public class WizBindingConstants { /** * The binding id. */ - public static final String BINDING_ID = "wizlighting"; + public static final String BINDING_ID = "wiz"; /** * List of all Thing Type UIDs. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java similarity index 67% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java index 725d733a6ff31..363066d713eb0 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/WizLightingHandlerFactory.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java @@ -10,14 +10,14 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal; +package org.openhab.binding.wiz.internal; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.handler.WizLightingHandler; -import org.openhab.binding.wizlighting.internal.handler.WizLightingMediator; +import org.openhab.binding.wiz.internal.handler.WizHandler; +import org.openhab.binding.wiz.internal.handler.WizMediator; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.BaseThingHandlerFactory; @@ -30,20 +30,20 @@ import org.slf4j.LoggerFactory; /** - * The {@link WizLightingHandlerFactory} is responsible for creating things and + * The {@link WizHandlerFactory} is responsible for creating things and * thing handlers. * * @author Sriram Balakrishnan - Initial contribution */ @NonNullByDefault -@Component(configurationPid = "binding.wizlighting", service = ThingHandlerFactory.class) -public class WizLightingHandlerFactory extends BaseThingHandlerFactory { - private final Logger logger = LoggerFactory.getLogger(WizLightingHandlerFactory.class); +@Component(configurationPid = "binding.wiz", service = ThingHandlerFactory.class) +public class WizHandlerFactory extends BaseThingHandlerFactory { + private final Logger logger = LoggerFactory.getLogger(WizHandlerFactory.class); - private final WizLightingMediator mediator; + private final WizMediator mediator; @Activate - public WizLightingHandlerFactory(@Reference WizLightingMediator mediator) { + public WizHandlerFactory(@Reference WizMediator mediator) { this.mediator = mediator; } @@ -57,9 +57,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (supportsThingType(thing.getThingTypeUID())) { - WizLightingHandler handler; + WizHandler handler; - handler = new WizLightingHandler(thing, this.mediator.getRegistrationParams()); + handler = new WizHandler(thing, this.mediator.getRegistrationParams()); mediator.registerThingAndWizBulbHandler(thing, handler); return handler; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java similarity index 84% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java index b673ab4e7799d..2de79930f1a41 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/config/WizLightingDeviceConfiguration.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.config; +package org.openhab.binding.wiz.internal.config; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -23,7 +23,7 @@ * @author Sara Geleskie Damiano - Initial contribution */ @NonNullByDefault -public class WizLightingDeviceConfiguration { +public class WizDeviceConfiguration { /** * Configuration for a Bond Bridge or Device diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java similarity index 85% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java index 0e8f96608e52d..87d56fda698e9 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/discovery/WizLightingDiscoveryService.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.discovery; +package org.openhab.binding.wiz.internal.discovery; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import java.io.IOException; import java.net.DatagramPacket; @@ -27,12 +27,12 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.entities.SystemConfigResult; -import org.openhab.binding.wizlighting.internal.entities.WizLightingRequest; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; -import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; -import org.openhab.binding.wizlighting.internal.handler.WizLightingMediator; -import org.openhab.binding.wizlighting.internal.utils.WizLightingPacketConverter; +import org.openhab.binding.wiz.internal.entities.SystemConfigResult; +import org.openhab.binding.wiz.internal.entities.WizRequest; +import org.openhab.binding.wiz.internal.entities.WizResponse; +import org.openhab.binding.wiz.internal.enums.WizMethodType; +import org.openhab.binding.wiz.internal.handler.WizMediator; +import org.openhab.binding.wiz.internal.utils.WizPacketConverter; import org.openhab.core.config.discovery.AbstractDiscoveryService; import org.openhab.core.config.discovery.DiscoveryResult; import org.openhab.core.config.discovery.DiscoveryResultBuilder; @@ -48,21 +48,21 @@ import org.slf4j.LoggerFactory; /** - * This is the {@link DiscoveryService} for the Wizlighting Items. + * This is the {@link DiscoveryService} for the WiZ Items. * * @author Sriram Balakrishnan - Initial contribution * @author Joshua Freeman - use configured Broadcast address instead of guessing, discovery of plugs * */ -@Component(configurationPid = "discovery.wizlighting", service = DiscoveryService.class, immediate = true) +@Component(configurationPid = "discovery.wiz", service = DiscoveryService.class, immediate = true) @NonNullByDefault -public class WizLightingDiscoveryService extends AbstractDiscoveryService { +public class WizDiscoveryService extends AbstractDiscoveryService { - private final Logger logger = LoggerFactory.getLogger(WizLightingDiscoveryService.class); + private final Logger logger = LoggerFactory.getLogger(WizDiscoveryService.class); - private final WizLightingMediator mediator; + private final WizMediator mediator; - private final WizLightingPacketConverter converter = new WizLightingPacketConverter(); + private final WizPacketConverter converter = new WizPacketConverter(); private @Nullable ScheduledFuture bulbBackgroudDiscovery; @@ -72,8 +72,8 @@ public class WizLightingDiscoveryService extends AbstractDiscoveryService { * @throws IllegalArgumentException if the timeout < 0 */ @Activate - public WizLightingDiscoveryService( - @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC) WizLightingMediator mediator) + public WizDiscoveryService( + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC) WizMediator mediator) throws IllegalArgumentException { super(SUPPORTED_THING_TYPES, DISCOVERY_TIMEOUT_SECONDS, true); this.mediator = mediator; @@ -116,8 +116,7 @@ protected void startScan() { String broadcastIp = this.mediator.getNetworkAddressService().getConfiguredBroadcastAddress(); if (broadcastIp != null) { InetAddress address = InetAddress.getByName(broadcastIp); - WizLightingRequest request = new WizLightingRequest(WizLightingMethodType.Registration, - this.mediator.getRegistrationParams()); + WizRequest request = new WizRequest(WizMethodType.Registration, this.mediator.getRegistrationParams()); request.setId(0); byte[] message = this.converter.transformToByteMessage(request); @@ -170,7 +169,7 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd String thisBulbLabel = "WiZ Full Color Bulb at " + lightIpAddress; ThingUID newThingId = new ThingUID(thisBulbType, lightMacAddress); - WizLightingResponse configResponse = getDiscoveredBulbConfig(lightIpAddress); + WizResponse configResponse = getDiscoveredBulbConfig(lightIpAddress); if (configResponse != null) { SystemConfigResult discoveredBulbConfig = configResponse.getSystemConfigResults(); if (discoveredBulbConfig != null) { @@ -221,10 +220,10 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd } } - private synchronized @Nullable WizLightingResponse getDiscoveredBulbConfig(final String lightIpAddress) { + private synchronized @Nullable WizResponse getDiscoveredBulbConfig(final String lightIpAddress) { DatagramSocket dsocket = null; try { - WizLightingRequest request = new WizLightingRequest(WizLightingMethodType.GetSystemConfig, null); + WizRequest request = new WizRequest(WizMethodType.GetSystemConfig, null); request.setId(1); byte[] message = this.converter.transformToByteMessage(request); @@ -258,11 +257,11 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd // SETTERS AND GETTERS /** - * Gets the {@link WizLightingMediator} of this binding. + * Gets the {@link WizMediator} of this binding. * - * @return {@link WizLightingMediator}. + * @return {@link WizMediator}. */ - public WizLightingMediator getMediator() { + public WizMediator getMediator() { return this.mediator; } } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java similarity index 94% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java index 7104c9f7423c8..4d986b18fdc77 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java @@ -10,10 +10,10 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.wizlighting.internal.utils.WizColorConverter; +import org.openhab.binding.wiz.internal.utils.WizColorConverter; import org.openhab.core.library.types.HSBType; import com.google.gson.annotations.Expose; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java similarity index 90% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java index b95d20e4b6bfd..677887de0f081 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ColorTemperatureRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.library.types.PercentType; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java similarity index 95% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java index e39c71a66ab13..e33ab3bc2b6fc 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/DimmingRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java similarity index 87% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java index 657d773920fa6..fa815cf7d2b44 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/ErrorResponseResult.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -18,7 +18,7 @@ import com.google.gson.annotations.Expose; /** - * This POJO represents the "result" of one WiZ Lighting Response "results" are + * This POJO represents the "result" of one WiZ Response "results" are * returned from registration, pulse, setPilot, and (presumably) setSysConfig * commands * diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java similarity index 94% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java index 87ed4958e366f..6978124ef85a0 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FanStateRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java similarity index 89% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java index 477fbab65b99b..949ec1522e0ef 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/FirstBeatResponseParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/Param.java similarity index 91% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/Param.java index c90db1756ecf9..f086955880119 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/Param.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/Param.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java similarity index 95% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java index a6b1f878040ef..34d88a9277ef8 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/PulseRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java similarity index 97% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java index d27276a6440ce..d22e23237da99 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/RegistrationRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java similarity index 94% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java index 7bc94e4ecdffa..9e4a6d1c721a4 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SceneRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java similarity index 95% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java index 21cafa5730b07..05d14eb2187a4 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SpeedRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java similarity index 94% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java index 6f7185e6f2210..764dfc38a82ba 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/StateRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java similarity index 94% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java index 29c3f2e981303..a88399def71cc 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/SystemConfigResult.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java similarity index 73% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java index ece85d8e93f32..5dae512e77838 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingRequest.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java @@ -10,27 +10,27 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; +import org.openhab.binding.wiz.internal.enums.WizMethodType; import com.google.gson.annotations.Expose; /** - * This POJO represents one WiZ Lighting UDP Request. + * This POJO represents one WiZ UDP Request. * * @author Sriram Balakrishnan - Initial contribution * */ @NonNullByDefault -public class WizLightingRequest { +public class WizRequest { @Expose(serialize = true, deserialize = true) private int id; @Expose(serialize = true, deserialize = true) - private WizLightingMethodType method; + private WizMethodType method; @Expose(serialize = false, deserialize = false) private String methodName; @@ -41,10 +41,10 @@ public class WizLightingRequest { /** * Default constructor. * - * @param type the {@link WizLightingMethodType} + * @param type the {@link WizMethodType} * @param params {@link Param} */ - public WizLightingRequest(final WizLightingMethodType method, final @Nullable Param params) { + public WizRequest(final WizMethodType method, final @Nullable Param params) { this.method = method; this.methodName = method.getMethodName(); this.params = params; @@ -58,11 +58,11 @@ public void setParams(final Param params) { this.params = params; } - public WizLightingMethodType getMethod() { + public WizMethodType getMethod() { return this.method; } - public void setMethod(final WizLightingMethodType method) { + public void setMethod(final WizMethodType method) { this.method = method; this.methodName = method.getMethodName(); } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java similarity index 84% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java index 12b736333860e..eb7a8b6b1a8ae 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingResponse.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java @@ -10,24 +10,24 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; +import org.openhab.binding.wiz.internal.enums.WizMethodType; import com.google.gson.annotations.Expose; /** - * This POJO represents one WiZ Lighting Response + * This POJO represents one WiZ Response * * @author Sriram Balakrishnan - Initial contribution * */ @NonNullByDefault -public class WizLightingResponse { +public class WizResponse { // The IP address we're coming from @Expose(serialize = false, deserialize = true) @@ -49,7 +49,7 @@ public class WizLightingResponse { // The method being used - see the enum for details // We're setting this to "unknown" @Expose(serialize = true, deserialize = true) - private WizLightingMethodType method = WizLightingMethodType.UnknownMethod; + private WizMethodType method = WizMethodType.UnknownMethod; // The MAC address the response is coming from @Expose(serialize = true, deserialize = true) @@ -69,7 +69,7 @@ public class WizLightingResponse { // from a get method is generally identical to the params returned in the // heartbeat. @Expose(serialize = true, deserialize = true) - private @Nullable WizLightingSyncState params; + private @Nullable WizSyncState params; /** * Setters and Getters @@ -91,11 +91,11 @@ public void setResultSucess(final boolean success) { this.success = success; } - public @Nullable WizLightingSyncState getSyncState() { + public @Nullable WizSyncState getSyncState() { return this.params; } - public void setSyncParams(final WizLightingSyncState params) { + public void setSyncParams(final WizSyncState params) { this.params = params; } @@ -123,11 +123,11 @@ public void setId(final int id) { this.id = id; } - public @Nullable WizLightingMethodType getMethod() { + public @Nullable WizMethodType getMethod() { return method; } - public void setMethod(final WizLightingMethodType method) { + public void setMethod(final WizMethodType method) { this.method = method; } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java similarity index 88% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index 501f5ec0eb7ee..0876945449552 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/entities/WizLightingSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -10,13 +10,13 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.entities; +package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.wizlighting.internal.enums.WizLightingColorMode; -import org.openhab.binding.wizlighting.internal.utils.WizColorConverter; +import org.openhab.binding.wiz.internal.enums.WizColorMode; +import org.openhab.binding.wiz.internal.utils.WizColorConverter; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.PercentType; @@ -30,7 +30,7 @@ * */ @NonNullByDefault -public class WizLightingSyncState { +public class WizSyncState { // The MAC address the response is coming from @Expose(serialize = true, deserialize = true) public String mac = MISSING_INVALID_MAC_ADDRESS; @@ -38,7 +38,7 @@ public class WizLightingSyncState { // The current color mode of the bulb // We will assume by default that it's a single color bulb @Expose(serialize = false, deserialize = false) - public WizLightingColorMode colorMode = WizLightingColorMode.SingleColorMode; + public WizColorMode colorMode = WizColorMode.SingleColorMode; @Expose(serialize = false, deserialize = false) private WizColorConverter colorConverter = new WizColorConverter(); @@ -104,18 +104,18 @@ public class WizLightingSyncState { @Expose(serialize = true, deserialize = true) public int fanRevrs; - public WizLightingColorMode getColorMode() { + public WizColorMode getColorMode() { if (r != 0 || g != 0 || b != 0) { - return WizLightingColorMode.RGBMode; + return WizColorMode.RGBMode; } else if (temp != 0) { - return WizLightingColorMode.CTMode; + return WizColorMode.CTMode; } else { - return WizLightingColorMode.SingleColorMode; + return WizColorMode.SingleColorMode; } } public HSBType getHSBColor() { - if (getColorMode() == WizLightingColorMode.RGBMode) { + if (getColorMode() == WizColorMode.RGBMode) { HSBType newColor = colorConverter.rgbwDimmingToHSB(r, g, b, w, dimming); // NOTE: The WiZ bulbs do not use the cool white LED's in full color mode. return newColor; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizColorMode.java similarity index 89% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizColorMode.java index 2189272e1ee3d..7ce62bd743829 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingColorMode.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizColorMode.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.enums; +package org.openhab.binding.wiz.internal.enums; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -25,7 +25,7 @@ * */ @NonNullByDefault -public enum WizLightingColorMode { +public enum WizColorMode { // Full color mode RGBMode("Full Color"), // Tunable white (color temperature) mode @@ -35,7 +35,7 @@ public enum WizLightingColorMode { private String colorMode; - private WizLightingColorMode(final String colorMode) { + private WizColorMode(final String colorMode) { this.colorMode = colorMode; } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java similarity index 75% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java index cfd6e6052213e..74ae23f40f5b0 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingLightMode.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.enums; +package org.openhab.binding.wiz.internal.enums; import java.util.HashMap; import java.util.Map; @@ -25,7 +25,7 @@ * */ @NonNullByDefault -public enum WizLightingLightMode { +public enum WizLightMode { Ocean("Ocean", 1), Romance("Romance", 2), Sunset("Sunset", 3), @@ -62,7 +62,7 @@ public enum WizLightingLightMode { private String colorModeName; private int sceneId; - private WizLightingLightMode(final String colorModeName, final int sceneId) { + private WizLightMode(final String colorModeName, final int sceneId) { this.colorModeName = colorModeName; this.sceneId = sceneId; } @@ -80,29 +80,29 @@ public int getSceneId() { return sceneId; } - private static final Map LIGHT_MODE_MAP_BY_ID; - private static final Map LIGHT_MODE_MAP_BY_NAME; + private static final Map LIGHT_MODE_MAP_BY_ID; + private static final Map LIGHT_MODE_MAP_BY_NAME; static { - LIGHT_MODE_MAP_BY_ID = new HashMap(); - LIGHT_MODE_MAP_BY_NAME = new HashMap(); + LIGHT_MODE_MAP_BY_ID = new HashMap(); + LIGHT_MODE_MAP_BY_NAME = new HashMap(); - for (WizLightingLightMode v : WizLightingLightMode.values()) { + for (WizLightMode v : WizLightMode.values()) { LIGHT_MODE_MAP_BY_ID.put(v.sceneId, v); LIGHT_MODE_MAP_BY_NAME.put(v.colorModeName.toLowerCase().replaceAll("\\W+", ""), v); } } - public static @Nullable WizLightingLightMode fromSceneId(int id) { - WizLightingLightMode r = null; + public static @Nullable WizLightMode fromSceneId(int id) { + WizLightMode r = null; if (id > 0 && id < 33) { r = LIGHT_MODE_MAP_BY_ID.get(id); } return r; } - public static @Nullable WizLightingLightMode fromSceneName(String name) { - WizLightingLightMode r = null; + public static @Nullable WizLightMode fromSceneName(String name) { + WizLightMode r = null; if (name != null && !"".equals(name)) { r = LIGHT_MODE_MAP_BY_NAME.get(name.toLowerCase().replaceAll("\\W+", "")); } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java similarity index 95% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java index 6c2e00843a954..951fa99a00d00 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingMethodType.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java @@ -10,20 +10,20 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.enums; +package org.openhab.binding.wiz.internal.enums; import org.eclipse.jdt.annotation.NonNullByDefault; import com.google.gson.annotations.SerializedName; /** - * This enum represents the available WiZ Lighting Request Methods + * This enum represents the available WiZ Request Methods * * @author Sriram Balakrishnan - Initial contribution * */ @NonNullByDefault -public enum WizLightingMethodType { +public enum WizMethodType { /** * Registration - used to "register" with the bulb: This notifies the bult that * it you want it to send you heartbeat sync packets. @@ -130,7 +130,7 @@ public enum WizLightingMethodType { private final String methodName; - private WizLightingMethodType(final String methodName) { + private WizMethodType(final String methodName) { this.methodName = methodName; } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizModuleType.java similarity index 82% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizModuleType.java index e77ac8a6e47bb..294d151b6ffc0 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/enums/WizLightingModuleType.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizModuleType.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.enums; +package org.openhab.binding.wiz.internal.enums; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import java.util.HashMap; import java.util.Map; @@ -28,7 +28,7 @@ * */ @NonNullByDefault -public enum WizLightingModuleType { +public enum WizModuleType { FullColorWifi("ESP01_SHRGB1C_31", THING_TYPE_COLOR_BULB), TunableWhiteWifi("ESP56_SHTW3_01", THING_TYPE_TUNABLE_BULB), DimmableWifi("TBD", THING_TYPE_DIMMABLE_BULB), @@ -37,7 +37,7 @@ public enum WizLightingModuleType { private final String moduleName; private final ThingTypeUID thingTypeUID; - private WizLightingModuleType(final String moduleName, final ThingTypeUID thingTypeUID) { + private WizModuleType(final String moduleName, final ThingTypeUID thingTypeUID) { this.moduleName = moduleName; this.thingTypeUID = thingTypeUID; } @@ -54,7 +54,7 @@ public String getModuleName() { private static final Map MODULE_NAME_MAP; static { MODULE_NAME_MAP = new HashMap(); - for (WizLightingModuleType v : WizLightingModuleType.values()) { + for (WizModuleType v : WizModuleType.values()) { MODULE_NAME_MAP.put(v.moduleName, v.thingTypeUID); } } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java similarity index 87% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index dc497933758df..0eaecd8e1429b 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.handler; +package org.openhab.binding.wiz.internal.handler; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import static org.openhab.core.thing.Thing.*; import java.io.IOException; @@ -27,24 +27,24 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.config.WizLightingDeviceConfiguration; -import org.openhab.binding.wizlighting.internal.entities.ColorRequestParam; -import org.openhab.binding.wizlighting.internal.entities.ColorTemperatureRequestParam; -import org.openhab.binding.wizlighting.internal.entities.DimmingRequestParam; -import org.openhab.binding.wizlighting.internal.entities.FanStateRequestParam; -import org.openhab.binding.wizlighting.internal.entities.Param; -import org.openhab.binding.wizlighting.internal.entities.RegistrationRequestParam; -import org.openhab.binding.wizlighting.internal.entities.SceneRequestParam; -import org.openhab.binding.wizlighting.internal.entities.SpeedRequestParam; -import org.openhab.binding.wizlighting.internal.entities.StateRequestParam; -import org.openhab.binding.wizlighting.internal.entities.SystemConfigResult; -import org.openhab.binding.wizlighting.internal.entities.WizLightingRequest; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; -import org.openhab.binding.wizlighting.internal.entities.WizLightingSyncState; -import org.openhab.binding.wizlighting.internal.enums.WizLightingLightMode; -import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; -import org.openhab.binding.wizlighting.internal.utils.ValidationUtils; -import org.openhab.binding.wizlighting.internal.utils.WizLightingPacketConverter; +import org.openhab.binding.wiz.internal.config.WizDeviceConfiguration; +import org.openhab.binding.wiz.internal.entities.ColorRequestParam; +import org.openhab.binding.wiz.internal.entities.ColorTemperatureRequestParam; +import org.openhab.binding.wiz.internal.entities.DimmingRequestParam; +import org.openhab.binding.wiz.internal.entities.FanStateRequestParam; +import org.openhab.binding.wiz.internal.entities.Param; +import org.openhab.binding.wiz.internal.entities.RegistrationRequestParam; +import org.openhab.binding.wiz.internal.entities.SceneRequestParam; +import org.openhab.binding.wiz.internal.entities.SpeedRequestParam; +import org.openhab.binding.wiz.internal.entities.StateRequestParam; +import org.openhab.binding.wiz.internal.entities.SystemConfigResult; +import org.openhab.binding.wiz.internal.entities.WizRequest; +import org.openhab.binding.wiz.internal.entities.WizResponse; +import org.openhab.binding.wiz.internal.entities.WizSyncState; +import org.openhab.binding.wiz.internal.enums.WizLightMode; +import org.openhab.binding.wiz.internal.enums.WizMethodType; +import org.openhab.binding.wiz.internal.utils.ValidationUtils; +import org.openhab.binding.wiz.internal.utils.WizPacketConverter; import org.openhab.core.config.core.Configuration; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DecimalType; @@ -69,23 +69,23 @@ import org.slf4j.LoggerFactory; /** - * The {@link WizLightingHandler} is responsible for handling commands, which + * The {@link WizHandler} is responsible for handling commands, which * are sent to one of the channels. * * @author Sriram Balakrishnan - Initial contribution */ @NonNullByDefault -public class WizLightingHandler extends BaseThingHandler { +public class WizHandler extends BaseThingHandler { - private final Logger logger = LoggerFactory.getLogger(WizLightingHandler.class); + private final Logger logger = LoggerFactory.getLogger(WizHandler.class); - private @NonNullByDefault({}) WizLightingDeviceConfiguration config; + private @NonNullByDefault({}) WizDeviceConfiguration config; private RegistrationRequestParam registrationInfo; private int homeId; - private WizLightingSyncState mostRecentState; + private WizSyncState mostRecentState; - private final WizLightingPacketConverter converter = new WizLightingPacketConverter(); + private final WizPacketConverter converter = new WizPacketConverter(); private @Nullable ScheduledFuture keepAliveJob; private long latestUpdate = -1; private long latestOfflineRefresh = -1; @@ -100,10 +100,10 @@ public class WizLightingHandler extends BaseThingHandler { * * @param thing the thing of the handler. */ - public WizLightingHandler(final Thing thing, final RegistrationRequestParam registrationPacket) { + public WizHandler(final Thing thing, final RegistrationRequestParam registrationPacket) { super(thing); this.registrationInfo = registrationPacket; - this.mostRecentState = new WizLightingSyncState(); + this.mostRecentState = new WizSyncState(); this.isFan = thing.getThingTypeUID().equals(THING_TYPE_CEILING_FAN); fullyInitialized = false; } @@ -219,7 +219,7 @@ private void handleLightModeCommand(Command command) { String commandAsString = command.toString(); Integer commandAsInt = Integer.MIN_VALUE; - WizLightingLightMode commandAsLightMode = null; + WizLightMode commandAsLightMode = null; try { commandAsInt = Integer.parseInt(commandAsString); @@ -227,11 +227,11 @@ private void handleLightModeCommand(Command command) { } if (commandAsInt > 0) { - commandAsLightMode = WizLightingLightMode.fromSceneId(commandAsInt); + commandAsLightMode = WizLightMode.fromSceneId(commandAsInt); } if (commandAsLightMode == null) { - commandAsLightMode = WizLightingLightMode.fromSceneName(commandAsString); + commandAsLightMode = WizLightMode.fromSceneName(commandAsString); } if (commandAsLightMode != null) { @@ -394,7 +394,7 @@ private synchronized void initGetStatusAndKeepAliveThread() { @Override public void initialize() { - this.config = getConfigAs(WizLightingDeviceConfiguration.class); + this.config = getConfigAs(WizDeviceConfiguration.class); fullyInitialized = false; disposed = false; @@ -421,9 +421,9 @@ public void dispose() { } private synchronized void getPilot() { - WizLightingResponse response = sendRequestPacket(WizLightingMethodType.GetPilot, null); + WizResponse response = sendRequestPacket(WizMethodType.GetPilot, null); if (response != null) { - WizLightingSyncState rParam = response.getSyncState(); + WizSyncState rParam = response.getSyncState(); if (rParam != null) { updateTimestamps(); updateStatesFromParams(rParam); @@ -436,7 +436,7 @@ private synchronized void getPilot() { } /** - * Method called by {@link WizLightingMediator} when any "unsolicited" messages + * Method called by {@link WizMediator} when any "unsolicited" messages * come in on the listening socket and appear to be a WiZ bulb. "Unsolicited" * messages from the bulb are could be: * - a "firstBeat" broadcast to the subnet by the bulb on first powering up @@ -448,9 +448,9 @@ private synchronized void getPilot() { * the message came from doesn't match the bulb's configured IP address, this will update the * bulb's configuration to reflect whatever the current IP is. * - * @param receivedMessage the received {@link WizLightingResponse}. + * @param receivedMessage the received {@link WizResponse}. */ - public synchronized void newReceivedResponseMessage(final WizLightingResponse receivedMessage) { + public synchronized void newReceivedResponseMessage(final WizResponse receivedMessage) { Boolean updatePropertiesAfterParams = false; // Check if the bulb still has the same IP address it had previously @@ -464,7 +464,7 @@ public synchronized void newReceivedResponseMessage(final WizLightingResponse re // save the changes to the thing updateConfiguration(priorConfig); // and then refresh the config within the handler - this.config = getConfigAs(WizLightingDeviceConfiguration.class); + this.config = getConfigAs(WizDeviceConfiguration.class); // finally, make note that we want to update properties updatePropertiesAfterParams = true; } @@ -474,7 +474,7 @@ public synchronized void newReceivedResponseMessage(final WizLightingResponse re updateTimestamps(); // Update the state from the parameters, if possible - WizLightingSyncState params = receivedMessage.getSyncState(); + WizSyncState params = receivedMessage.getSyncState(); if (params != null) { updateStatesFromParams(params); } @@ -489,9 +489,9 @@ public synchronized void newReceivedResponseMessage(final WizLightingResponse re /** * Updates the channel states based on incoming parameters * - * @param receivedParam The received {@link WizLightingSyncState} + * @param receivedParam The received {@link WizSyncState} */ - private synchronized void updateStatesFromParams(final WizLightingSyncState receivedParam) { + private synchronized void updateStatesFromParams(final WizSyncState receivedParam) { // Save the current state this.mostRecentState = receivedParam; @@ -526,9 +526,9 @@ private synchronized void updateStatesFromParams(final WizLightingSyncState rece /** * Updates the channel states for a light based on incoming parameters * - * @param receivedParam The received {@link WizLightingSyncState} + * @param receivedParam The received {@link WizSyncState} */ - private void updateLightStatesFromParams(final WizLightingSyncState receivedParam) { + private void updateLightStatesFromParams(final WizSyncState receivedParam) { if (!receivedParam.state) { updateState(CHANNEL_COLOR, HSBType.BLACK); updateState(CHANNEL_BRIGHTNESS, PercentType.ZERO); @@ -574,9 +574,9 @@ private void updateLightStatesFromParams(final WizLightingSyncState receivedPara /** * Updates the channel states for a fan based on incoming parameters * - * @param receivedParam The received {@link WizLightingSyncState} + * @param receivedParam The received {@link WizSyncState} */ - private void updateFanStatesFromParams(final WizLightingSyncState receivedParam) { + private void updateFanStatesFromParams(final WizSyncState receivedParam) { updateState(CHANNEL_STATE, new DecimalType(receivedParam.fanState)); updateState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); updateState(CHANNEL_REVERSE, new DecimalType(receivedParam.fanRevrs)); @@ -584,18 +584,18 @@ private void updateFanStatesFromParams(final WizLightingSyncState receivedParam) } /** - * Sends {@link WizLightingRequest} to the passed {@link InetAddress}. + * Sends {@link WizRequest} to the passed {@link InetAddress}. * - * @param requestPacket the {@link WizLightingRequest}. + * @param requestPacket the {@link WizRequest}. * @param address the {@link InetAddress}. */ - private synchronized @Nullable WizLightingResponse sendRequestPacket(final WizLightingMethodType method, + private synchronized @Nullable WizResponse sendRequestPacket(final WizMethodType method, final @Nullable Param param) { DatagramSocket dsocket = null; try { InetAddress address = InetAddress.getByName(config.bulbIpAddress); if (address != null) { - WizLightingRequest request = new WizLightingRequest(method, param); + WizRequest request = new WizRequest(method, param); request.setId(requestId++); byte[] message = this.converter.transformToByteMessage(request); @@ -637,7 +637,7 @@ private void updateFanStatesFromParams(final WizLightingSyncState receivedParam) * Sends a setPilot request and checks for success */ private synchronized boolean setPilotCommand(final @Nullable Param param) { - WizLightingResponse response = sendRequestPacket(WizLightingMethodType.SetPilot, param); + WizResponse response = sendRequestPacket(WizMethodType.SetPilot, param); if (response != null) { boolean setSucceeded = response.getResultSuccess(); if (setSucceeded) { @@ -675,7 +675,7 @@ private synchronized void updateBulbProperties() { if (hasConfigurationError() || disposed) { return; } - WizLightingResponse registrationResponse = sendRequestPacket(WizLightingMethodType.GetSystemConfig, null); + WizResponse registrationResponse = sendRequestPacket(WizMethodType.GetSystemConfig, null); if (registrationResponse != null) { SystemConfigResult responseResult = registrationResponse.getSystemConfigResults(); if (responseResult != null) { @@ -715,8 +715,7 @@ private synchronized void updateBulbProperties() { * heart-beats the registration must be re-sent after 30s. */ private synchronized void registerWithBulb() { - WizLightingResponse registrationResponse = sendRequestPacket(WizLightingMethodType.Registration, - this.registrationInfo); + WizResponse registrationResponse = sendRequestPacket(WizMethodType.Registration, this.registrationInfo); if (registrationResponse != null) { if (registrationResponse.getResultSuccess()) { updateTimestamps(); diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java similarity index 66% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java index 8da2da71257ea..bc9ed8169f510 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediator.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java @@ -10,35 +10,35 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.handler; +package org.openhab.binding.wiz.internal.handler; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.discovery.WizLightingDiscoveryService; -import org.openhab.binding.wizlighting.internal.entities.RegistrationRequestParam; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wiz.internal.discovery.WizDiscoveryService; +import org.openhab.binding.wiz.internal.entities.RegistrationRequestParam; +import org.openhab.binding.wiz.internal.entities.WizResponse; import org.openhab.core.net.NetworkAddressService; import org.openhab.core.thing.Thing; /** - * The {@link WizLightingMediator} is responsible for receiving all the sync + * The {@link WizMediator} is responsible for receiving all the sync * packets and route correctly to each handler. * * @author Sriram Balakrishnan - Initial contribution * @author Joshua Freeman - pass through NetworkAddressService */ @NonNullByDefault -public interface WizLightingMediator { +public interface WizMediator { /** - * This method is called by the {@link WizLightingUpdateReceiverRunnable}, when + * This method is called by the {@link WizUpdateReceiverRunnable}, when * one new message has been received. * - * @param receivedMessage the {@link WizLightingResponse} message. + * @param receivedMessage the {@link WizResponse} message. */ - void processReceivedPacket(final WizLightingResponse receivedMessage); + void processReceivedPacket(final WizResponse receivedMessage); /** * Returns a {@link RegistrationRequestParam} based on the current OpenHAB @@ -49,15 +49,15 @@ public interface WizLightingMediator { /** * Registers a new {@link Thing} and the corresponding - * {@link WizLightingHandler}. + * {@link WizHandler}. * * @param thing the {@link Thing}. - * @param handler the {@link WizLightingHandler}. + * @param handler the {@link WizHandler}. */ - void registerThingAndWizBulbHandler(final Thing thing, final WizLightingHandler handler); + void registerThingAndWizBulbHandler(final Thing thing, final WizHandler handler); /** - * Unregisters a {@link WizLightingHandler} by the corresponding {@link Thing}. + * Unregisters a {@link WizHandler} by the corresponding {@link Thing}. * * @param thing the {@link Thing}. */ @@ -76,7 +76,7 @@ public interface WizLightingMediator { * * @param discoveryService the discovery service. */ - void setDiscoveryService(final @Nullable WizLightingDiscoveryService discoveryService); + void setDiscoveryService(final @Nullable WizDiscoveryService discoveryService); /** * Gets the NetworkAddressService used to configure the mediator instance. diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java similarity index 70% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java index dba9de48e74e8..1f427b63d9d43 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/handler/WizLightingMediatorImpl.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java @@ -10,9 +10,9 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.handler; +package org.openhab.binding.wiz.internal.handler; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import java.net.SocketException; import java.util.HashMap; @@ -21,11 +21,11 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.discovery.WizLightingDiscoveryService; -import org.openhab.binding.wizlighting.internal.entities.RegistrationRequestParam; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; -import org.openhab.binding.wizlighting.internal.runnable.WizLightingUpdateReceiverRunnable; -import org.openhab.binding.wizlighting.internal.utils.NetworkUtils; +import org.openhab.binding.wiz.internal.discovery.WizDiscoveryService; +import org.openhab.binding.wiz.internal.entities.RegistrationRequestParam; +import org.openhab.binding.wiz.internal.entities.WizResponse; +import org.openhab.binding.wiz.internal.runnable.WizUpdateReceiverRunnable; +import org.openhab.binding.wiz.internal.utils.NetworkUtils; import org.openhab.core.net.NetworkAddressService; import org.openhab.core.thing.Thing; import org.osgi.service.component.ComponentContext; @@ -38,24 +38,24 @@ import org.slf4j.LoggerFactory; /** - * The {@link WizLightingMediatorImpl} is responsible for receiving all the sync + * The {@link WizMediatorImpl} is responsible for receiving all the sync * packets and route correctly to each handler. * * @author Sriram Balakrishnan - Initial contribution * @author Joshua Freeman - pass through NetworkAddressService */ -@Component(configurationPid = "WizLightingMediator", service = WizLightingMediator.class) +@Component(configurationPid = "WizMediator", service = WizMediator.class) @NonNullByDefault -public class WizLightingMediatorImpl implements WizLightingMediator { +public class WizMediatorImpl implements WizMediator { - private final Logger logger = LoggerFactory.getLogger(WizLightingMediatorImpl.class); + private final Logger logger = LoggerFactory.getLogger(WizMediatorImpl.class); - private final Map handlersRegisteredByThing = new HashMap<>(); + private final Map handlersRegisteredByThing = new HashMap<>(); - private @Nullable WizLightingUpdateReceiverRunnable receiver; - private @Nullable Thread wizLightingReceiverThread; + private @Nullable WizUpdateReceiverRunnable receiver; + private @Nullable Thread receiverThread; - private @Nullable WizLightingDiscoveryService wizlightingDiscoveryService; + private @Nullable WizDiscoveryService wizDiscoveryService; private final NetworkAddressService networkAddressService; @@ -65,7 +65,7 @@ public class WizLightingMediatorImpl implements WizLightingMediator { * @param IllegalArgumentException if the timeout < 0 */ @Activate - public WizLightingMediatorImpl( + public WizMediatorImpl( @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.STATIC) NetworkAddressService networkAddressService) { this.networkAddressService = networkAddressService; this.initMediatorWizBulbUpdateReceiverRunnable(); @@ -77,20 +77,20 @@ public WizLightingMediatorImpl( * @param componentContext the componentContext */ protected void deactivate(final ComponentContext componentContext) { - WizLightingUpdateReceiverRunnable receiver = this.receiver; + WizUpdateReceiverRunnable receiver = this.receiver; if (receiver != null) { receiver.shutdown(); } } /** - * This method is called by the {@link WizLightingUpdateReceiverRunnable}, when + * This method is called by the {@link WizUpdateReceiverRunnable}, when * one new message has been received. * - * @param receivedMessage the {@link WizLightingResponse} message. + * @param receivedMessage the {@link WizResponse} message. */ @Override - public void processReceivedPacket(final WizLightingResponse receivedMessage) { + public void processReceivedPacket(final WizResponse receivedMessage) { logger.debug("Received packet from: {} - {} with method: [{}]", receivedMessage.getWizResponseIpAddress(), receivedMessage.getWizResponseMacAddress(), receivedMessage.getMethod()); @@ -99,7 +99,7 @@ public void processReceivedPacket(final WizLightingResponse receivedMessage) { if (!bulbMac.equals(MISSING_INVALID_MAC_ADDRESS)) { @Nullable - WizLightingHandler handler = this.getHandlerRegisteredByMac(bulbMac); + WizHandler handler = this.getHandlerRegisteredByMac(bulbMac); if (handler != null) { // deliver message to handler. @@ -107,7 +107,7 @@ public void processReceivedPacket(final WizLightingResponse receivedMessage) { } else if (!bulbIp.equals(MISSING_INVALID_IP_ADDRESS)) { logger.debug("There is no handler registered for mac address: {}", receivedMessage.getWizResponseMacAddress()); - WizLightingDiscoveryService discoveryServe = this.wizlightingDiscoveryService; + WizDiscoveryService discoveryServe = this.wizDiscoveryService; if (discoveryServe != null) { discoveryServe.discoveredLight(bulbMac, bulbIp); logger.trace("Sending a new thing to the discovery service. MAC: {} IP: {}", bulbMac, bulbIp); @@ -122,18 +122,18 @@ public void processReceivedPacket(final WizLightingResponse receivedMessage) { /** * Register one new {@link Thing} and the corresponding - * {@link WizLightingHandler}. + * {@link WizHandler}. * * @param thing the {@link Thing}. - * @param handler the {@link WizLightingHandler}. + * @param handler the {@link WizHandler}. */ @Override - public void registerThingAndWizBulbHandler(final Thing thing, final WizLightingHandler handler) { + public void registerThingAndWizBulbHandler(final Thing thing, final WizHandler handler) { this.handlersRegisteredByThing.put(thing, handler); } /** - * Unregister one {@link WizLightingHandler} by the corresponding {@link Thing}. + * Unregister one {@link WizHandler} by the corresponding {@link Thing}. * * @param thing the {@link Thing}. */ @@ -147,11 +147,11 @@ public void unregisterWizBulbHandlerByThing(final Thing thing) { * address. * * @param bulbMacAddress the mac address of the thing of the handler. - * @return {@link WizLightingHandler} if found. + * @return {@link WizHandler} if found. */ - private @Nullable WizLightingHandler getHandlerRegisteredByMac(final String bulbMacAddress) { - WizLightingHandler searchedHandler = null; - for (WizLightingHandler handler : this.handlersRegisteredByThing.values()) { + private @Nullable WizHandler getHandlerRegisteredByMac(final String bulbMacAddress) { + WizHandler searchedHandler = null; + for (WizHandler handler : this.handlersRegisteredByThing.values()) { if (bulbMacAddress.equalsIgnoreCase(handler.getBulbMacAddress())) { searchedHandler = handler; // don't spend more computation. Found the handler. @@ -167,21 +167,20 @@ public void unregisterWizBulbHandlerByThing(final Thing thing) { * to mediator. */ private void initMediatorWizBulbUpdateReceiverRunnable() { - WizLightingUpdateReceiverRunnable receiver = this.receiver; - Thread receiverThread = this.wizLightingReceiverThread; + WizUpdateReceiverRunnable receiver = this.receiver; + Thread receiverThread = this.receiverThread; // try with handler port if is null if ((receiver == null) || ((receiverThread != null) && (receiverThread.isInterrupted() || !receiverThread.isAlive()))) { try { logger.trace("Receiver thread is either null, interrupted, or dead."); - WizLightingUpdateReceiverRunnable newReceiver = new WizLightingUpdateReceiverRunnable(this, - DEFAULT_LISTENER_UDP_PORT); + WizUpdateReceiverRunnable newReceiver = new WizUpdateReceiverRunnable(this, DEFAULT_LISTENER_UDP_PORT); Thread newThread = new Thread(newReceiver); newThread.setDaemon(true); newThread.start(); - newThread.setName("wizLightingReceiverThread"); + newThread.setName("wizReceiverThread"); this.receiver = newReceiver; - this.wizLightingReceiverThread = newThread; + this.receiverThread = newThread; } catch (SocketException e) { logger.debug("Cannot start the socket with default port {}...", e.getMessage()); } @@ -232,12 +231,12 @@ public RegistrationRequestParam getRegistrationParams() { } @Override - public void setDiscoveryService(final @Nullable WizLightingDiscoveryService discoveryService) { - this.wizlightingDiscoveryService = discoveryService; + public void setDiscoveryService(final @Nullable WizDiscoveryService discoveryService) { + this.wizDiscoveryService = discoveryService; } - public @Nullable WizLightingDiscoveryService getDiscoveryService() { - return this.wizlightingDiscoveryService; + public @Nullable WizDiscoveryService getDiscoveryService() { + return this.wizDiscoveryService; } @Override diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java similarity index 81% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java index 16dd066f1b165..57912fcb9a043 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/runnable/WizLightingUpdateReceiverRunnable.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.runnable; +package org.openhab.binding.wiz.internal.runnable; import java.io.IOException; import java.net.DatagramPacket; @@ -20,29 +20,29 @@ import java.net.SocketTimeoutException; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; -import org.openhab.binding.wizlighting.internal.handler.WizLightingMediator; -import org.openhab.binding.wizlighting.internal.utils.WizLightingPacketConverter; +import org.openhab.binding.wiz.internal.entities.WizResponse; +import org.openhab.binding.wiz.internal.handler.WizMediator; +import org.openhab.binding.wiz.internal.utils.WizPacketConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This Thread is responsible to receive all sync messages and redirect them to - * {@link WizLightingMediator}. + * {@link WizMediator}. * * @author Sriram Balakrishnan - Initial contribution * */ @NonNullByDefault -public class WizLightingUpdateReceiverRunnable implements Runnable { +public class WizUpdateReceiverRunnable implements Runnable { private static final int TIMEOUT_TO_DATAGRAM_RECEPTION_MILLISECONDS = 15000; - private final Logger logger = LoggerFactory.getLogger(WizLightingUpdateReceiverRunnable.class); + private final Logger logger = LoggerFactory.getLogger(WizUpdateReceiverRunnable.class); private DatagramSocket datagramSocket; - private final WizLightingMediator mediator; - private final WizLightingPacketConverter packetConverter = new WizLightingPacketConverter(); + private final WizMediator mediator; + private final WizPacketConverter packetConverter = new WizPacketConverter(); private boolean shutdown; private int listeningPort; @@ -50,12 +50,11 @@ public class WizLightingUpdateReceiverRunnable implements Runnable { /** * Constructor of the receiver runnable thread. * - * @param mediator the {@link WizLightingMediator} + * @param mediator the {@link WizMediator} * @param listeningPort the listening UDP port * @throws SocketException is some problem occurs opening the socket. */ - public WizLightingUpdateReceiverRunnable(final WizLightingMediator mediator, final int listeningPort) - throws SocketException { + public WizUpdateReceiverRunnable(final WizMediator mediator, final int listeningPort) throws SocketException { this.listeningPort = listeningPort; this.mediator = mediator; @@ -91,11 +90,11 @@ public void run() { datagramSocket.receive(packet); // Redirect packet to the mediator - WizLightingResponse response = this.packetConverter.transformResponsePacket(packet); + WizResponse response = this.packetConverter.transformResponsePacket(packet); if (response != null) { this.mediator.processReceivedPacket(response); } else { - logger.debug("No WizLightingResponse was parsed from returned packet"); + logger.debug("No WizResponse was parsed from returned packet"); } } catch (SocketTimeoutException e) { logger.trace("No incoming data on port {} during {} ms socket was listening.", listeningPort, diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java similarity index 97% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java index 29c44d92725e5..eb3daa95d9b19 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/NetworkUtils.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.utils; +package org.openhab.binding.wiz.internal.utils; import java.net.InterfaceAddress; import java.net.NetworkInterface; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java similarity index 96% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java index 9a070260bc592..f40f2cc20415a 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/ValidationUtils.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.utils; +package org.openhab.binding.wiz.internal.utils; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java similarity index 99% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java index 365eeec34a082..02b663d0642ad 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizColorConverter.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.utils; +package org.openhab.binding.wiz.internal.utils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.library.types.DecimalType; diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java similarity index 62% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java index 5f65cb563c4b0..414f2e3c45a2b 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizLightingPacketConverter.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.utils; +package org.openhab.binding.wiz.internal.utils; import static java.nio.charset.StandardCharsets.*; @@ -18,8 +18,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.entities.WizLightingRequest; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; +import org.openhab.binding.wiz.internal.entities.WizRequest; +import org.openhab.binding.wiz.internal.entities.WizResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,35 +34,35 @@ * */ @NonNullByDefault -public class WizLightingPacketConverter { +public class WizPacketConverter { - private final Logger logger = LoggerFactory.getLogger(WizLightingPacketConverter.class); + private final Logger logger = LoggerFactory.getLogger(WizPacketConverter.class); - private Gson wizlightingGsonBuilder; + private Gson wizGsonBuilder; /** * Default constructor of the packet converter. */ - public WizLightingPacketConverter() { + public WizPacketConverter() { GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(WizLightingResponse.class, new WizResponseDeserializer()); + gsonBuilder.registerTypeAdapter(WizResponse.class, new WizResponseDeserializer()); gsonBuilder.excludeFieldsWithoutExposeAnnotation(); // gsonBuilder.setLenient(); Gson gson = gsonBuilder.create(); - this.wizlightingGsonBuilder = gson; + this.wizGsonBuilder = gson; } /** - * Method that transforms one {@link WizLightingRequest} to json requst + * Method that transforms one {@link WizRequest} to json requst * - * @param requestPacket the {@link WizLightingRequest}. + * @param requestPacket the {@link WizRequest}. * @return the byte array with the message. */ - public byte[] transformToByteMessage(final WizLightingRequest requestPacket) { + public byte[] transformToByteMessage(final WizRequest requestPacket) { byte[] requestDatagram = null; // {"id":20,"method":"setPilot","params":{"sceneId":18}} - String jsonCmd = this.wizlightingGsonBuilder.toJson(requestPacket); + String jsonCmd = this.wizGsonBuilder.toJson(requestPacket); requestDatagram = jsonCmd.getBytes(UTF_8); return requestDatagram; @@ -70,19 +70,19 @@ public byte[] transformToByteMessage(final WizLightingRequest requestPacket) { /** * Method that transforms {@link DatagramPacket} to a - * {@link WizLightingResponse} Object + * {@link WizResponse} Object * * @param packet the {@link DatagramPacket} - * @return the {@link WizLightingResponse} + * @return the {@link WizResponse} */ - public @Nullable WizLightingResponse transformResponsePacket(final DatagramPacket packet) { + public @Nullable WizResponse transformResponsePacket(final DatagramPacket packet) { String responseJson = new String(packet.getData(), 0, packet.getLength(), UTF_8); logger.debug("Incoming packet from {} to convert -> {}", packet.getAddress().getHostAddress(), responseJson); @Nullable - WizLightingResponse response = null; + WizResponse response = null; try { - response = this.wizlightingGsonBuilder.fromJson(responseJson, WizLightingResponse.class); + response = this.wizGsonBuilder.fromJson(responseJson, WizResponse.class); response.setWizResponseIpAddress(packet.getAddress().getHostAddress()); } catch (JsonParseException e) { logger.error("Error parsing json! {}", e.getMessage()); diff --git a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java similarity index 89% rename from bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java rename to bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java index e3e430c077a6e..66f6cdbcd0d61 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/java/org/openhab/binding/wizlighting/internal/utils/WizResponseDeserializer.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java @@ -10,19 +10,19 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.wizlighting.internal.utils; +package org.openhab.binding.wiz.internal.utils; -import static org.openhab.binding.wizlighting.internal.WizLightingBindingConstants.*; +import static org.openhab.binding.wiz.internal.WizBindingConstants.*; import java.lang.reflect.Type; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.wizlighting.internal.entities.ErrorResponseResult; -import org.openhab.binding.wizlighting.internal.entities.SystemConfigResult; -import org.openhab.binding.wizlighting.internal.entities.WizLightingResponse; -import org.openhab.binding.wizlighting.internal.entities.WizLightingSyncState; -import org.openhab.binding.wizlighting.internal.enums.WizLightingMethodType; +import org.openhab.binding.wiz.internal.entities.ErrorResponseResult; +import org.openhab.binding.wiz.internal.entities.SystemConfigResult; +import org.openhab.binding.wiz.internal.entities.WizResponse; +import org.openhab.binding.wiz.internal.entities.WizSyncState; +import org.openhab.binding.wiz.internal.enums.WizMethodType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,16 +40,16 @@ */ @NonNullByDefault -public class WizResponseDeserializer implements JsonDeserializer { +public class WizResponseDeserializer implements JsonDeserializer { // We can't do too much logging, can we? private final Logger logger = LoggerFactory.getLogger(WizResponseDeserializer.class); @Override @Nullable - public WizLightingResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOfT, + public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOfT, @Nullable JsonDeserializationContext context) throws JsonParseException { // The outgoing response - WizLightingResponse deserializedResponse = new WizLightingResponse(); + WizResponse deserializedResponse = new WizResponse(); // The incoming JSON JsonObject jobject; @@ -86,12 +86,12 @@ public WizLightingResponse deserialize(@Nullable JsonElement json, @Nullable Typ // Parse the method. We will use the method to decide how to continue to parse // Bail out of everything if we cannot understand the method. - WizLightingMethodType method; + WizMethodType method; if (jobject.has("method")) { try { String inMethod = jobject.get("method").getAsString(); String properCaseMethod = inMethod.substring(0, 1).toUpperCase() + inMethod.substring(1); - method = WizLightingMethodType.valueOf(properCaseMethod); + method = WizMethodType.valueOf(properCaseMethod); deserializedResponse.setMethod(method); } catch (IllegalArgumentException e) { logger.warn("Bulb returned an invalid method: {}", jobject.get("method")); @@ -174,8 +174,8 @@ public WizLightingResponse deserialize(@Nullable JsonElement json, @Nullable Typ if (!jobject.has("result")) { throw new JsonParseException("getPilot received, but no result object present"); } - WizLightingSyncState parsedPResult = context.deserialize(jobject.getAsJsonObject("result"), - WizLightingSyncState.class); + WizSyncState parsedPResult = context.deserialize(jobject.getAsJsonObject("result"), + WizSyncState.class); if (parsedPResult.mac == MISSING_INVALID_MAC_ADDRESS) { throw new JsonParseException("getPilot received, but no MAC address present"); } @@ -192,8 +192,8 @@ public WizLightingResponse deserialize(@Nullable JsonElement json, @Nullable Typ if (!jobject.has("params")) { throw new JsonParseException("syncPilot received, but no params object present"); } - WizLightingSyncState parsedPParam = context.deserialize(jobject.getAsJsonObject("params"), - WizLightingSyncState.class); + WizSyncState parsedPParam = context.deserialize(jobject.getAsJsonObject("params"), + WizSyncState.class); if (parsedPParam.mac == MISSING_INVALID_MAC_ADDRESS) { throw new JsonParseException("syncPilot received, but no MAC address present"); } diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/addon/addon.xml similarity index 59% rename from bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml rename to bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/addon/addon.xml index 3f473e986eef7..4878c61dfc82c 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/addon/addon.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/addon/addon.xml @@ -1,11 +1,11 @@ - binding - WiZ Lighting Binding - Binding for WiZ Lighting smart bulbs. + WiZ Binding + Binding for WiZ smart devices. local diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/config/config.xml similarity index 100% rename from bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/config/config.xml rename to bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/config/config.xml diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties new file mode 100644 index 0000000000000..017a3fbe26fe0 --- /dev/null +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties @@ -0,0 +1,72 @@ +# add-on + +addon.wiz.name = WiZ Binding +addon.wiz.description = Binding for WiZ smart devices. + +# thing types + +thing-type.wiz.ceiling-fan.label = WiZ Ceiling Fan +thing-type.wiz.ceiling-fan.description = Supports WiZ Ceiling Fans +thing-type.wiz.color-bulb.label = WiZ Color Bulb +thing-type.wiz.color-bulb.description = Supports WiZ Full Color with Tunable White Bulbs +thing-type.wiz.dimmable-bulb.label = WiZ Dimmable Bulb +thing-type.wiz.dimmable-bulb.description = Supports WiZ Single Color Dimmable Bulbs +thing-type.wiz.plug.label = WiZ Smart Plug +thing-type.wiz.plug.description = Supports WiZ Smart Plugs +thing-type.wiz.tunable-bulb.label = WiZ Tunable Bulb +thing-type.wiz.tunable-bulb.description = Supports WiZ Tunable White Bulbs + +# thing types config + +thing-type.config.wiz.light.bulbIpAddress.label = Bulb IP Address +thing-type.config.wiz.light.bulbIpAddress.description = IP address of the bulb +thing-type.config.wiz.light.bulbMacAddress.label = Bulb MAC Address +thing-type.config.wiz.light.bulbMacAddress.description = MAC address of the bulb +thing-type.config.wiz.light.reconnectInterval.label = Reconnect Interval +thing-type.config.wiz.light.reconnectInterval.description = Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. +thing-type.config.wiz.light.updateInterval.label = Update Interval +thing-type.config.wiz.light.updateInterval.description = Update time interval in seconds to request the status of the bulb while it is connected to the network. +thing-type.config.wiz.light.useHeartBeats.label = Use Heartbeats +thing-type.config.wiz.light.useHeartBeats.description = True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. + +# channel types + +channel-type.wiz.color-temperature-abs.label = Color Temperature +channel-type.wiz.color-temperature-abs.description = Controls the color temperature of the light in Kelvin +channel-type.wiz.last-update.label = Last Update +channel-type.wiz.last-update.description = Timestamp of last status update +channel-type.wiz.light-mode.label = Light Mode +channel-type.wiz.light-mode.state.option.1 = Ocean +channel-type.wiz.light-mode.state.option.2 = Romance +channel-type.wiz.light-mode.state.option.3 = Sunset +channel-type.wiz.light-mode.state.option.4 = Party +channel-type.wiz.light-mode.state.option.5 = Fireplace +channel-type.wiz.light-mode.state.option.6 = Cozy White +channel-type.wiz.light-mode.state.option.7 = Forest +channel-type.wiz.light-mode.state.option.8 = Pastel Colors +channel-type.wiz.light-mode.state.option.9 = Wakeup +channel-type.wiz.light-mode.state.option.10 = Bed Time +channel-type.wiz.light-mode.state.option.11 = Warm White +channel-type.wiz.light-mode.state.option.12 = Daylight +channel-type.wiz.light-mode.state.option.13 = Cool White +channel-type.wiz.light-mode.state.option.14 = Night Light +channel-type.wiz.light-mode.state.option.15 = Focus +channel-type.wiz.light-mode.state.option.16 = Relax +channel-type.wiz.light-mode.state.option.17 = True Colors +channel-type.wiz.light-mode.state.option.18 = TV Time +channel-type.wiz.light-mode.state.option.19 = Plant Growth +channel-type.wiz.light-mode.state.option.20 = Spring +channel-type.wiz.light-mode.state.option.21 = Summer +channel-type.wiz.light-mode.state.option.22 = Fall +channel-type.wiz.light-mode.state.option.23 = Deep Dive +channel-type.wiz.light-mode.state.option.24 = Jungle +channel-type.wiz.light-mode.state.option.25 = Mojito +channel-type.wiz.light-mode.state.option.26 = Club +channel-type.wiz.light-mode.state.option.27 = Christmas +channel-type.wiz.light-mode.state.option.28 = Halloween +channel-type.wiz.light-mode.state.option.29 = Candlelight +channel-type.wiz.light-mode.state.option.30 = Golden White +channel-type.wiz.light-mode.state.option.31 = Pulse +channel-type.wiz.light-mode.state.option.32 = Steampunk +channel-type.wiz.speed.label = Dynamic Light Mode Speed +channel-type.wiz.speed.description = Speed of color/intensity changes in dynamic light modes diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml similarity index 98% rename from bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml rename to bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index f7e3627ec1b6a..614b79e7fd053 100644 --- a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -1,6 +1,5 @@ - diff --git a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties b/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties deleted file mode 100644 index 9238ab0a83761..0000000000000 --- a/bundles/org.openhab.binding.wizlighting/src/main/resources/OH-INF/i18n/wizlighting.properties +++ /dev/null @@ -1,72 +0,0 @@ -# add-on - -addon.wizlighting.name = WiZ Lighting Binding -addon.wizlighting.description = Binding for WiZ Lighting smart bulbs. - -# thing types - -thing-type.wizlighting.ceiling-fan.label = WiZ Ceiling Fan -thing-type.wizlighting.ceiling-fan.description = Supports WiZ Ceiling Fans -thing-type.wizlighting.color-bulb.label = WiZ Color Bulb -thing-type.wizlighting.color-bulb.description = Supports WiZ Full Color with Tunable White Bulbs -thing-type.wizlighting.dimmable-bulb.label = WiZ Dimmable Bulb -thing-type.wizlighting.dimmable-bulb.description = Supports WiZ Single Color Dimmable Bulbs -thing-type.wizlighting.plug.label = WiZ Smart Plug -thing-type.wizlighting.plug.description = Supports WiZ Smart Plugs -thing-type.wizlighting.tunable-bulb.label = WiZ Tunable Bulb -thing-type.wizlighting.tunable-bulb.description = Supports WiZ Tunable White Bulbs - -# thing types config - -thing-type.config.wiz.light.bulbIpAddress.label = Bulb IP Address -thing-type.config.wiz.light.bulbIpAddress.description = IP address of the bulb -thing-type.config.wiz.light.bulbMacAddress.label = Bulb MAC Address -thing-type.config.wiz.light.bulbMacAddress.description = MAC address of the bulb -thing-type.config.wiz.light.reconnectInterval.label = Reconnect Interval -thing-type.config.wiz.light.reconnectInterval.description = Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. -thing-type.config.wiz.light.updateInterval.label = Update Interval -thing-type.config.wiz.light.updateInterval.description = Update time interval in seconds to request the status of the bulb while it is connected to the network. -thing-type.config.wiz.light.useHeartBeats.label = Use Heartbeats -thing-type.config.wiz.light.useHeartBeats.description = True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. - -# channel types - -channel-type.wizlighting.color-temperature-abs.label = Color Temperature -channel-type.wizlighting.color-temperature-abs.description = Controls the color temperature of the light in Kelvin -channel-type.wizlighting.last-update.label = Last Update -channel-type.wizlighting.last-update.description = Timestamp of last status update -channel-type.wizlighting.light-mode.label = Light Mode -channel-type.wizlighting.light-mode.state.option.1 = Ocean -channel-type.wizlighting.light-mode.state.option.2 = Romance -channel-type.wizlighting.light-mode.state.option.3 = Sunset -channel-type.wizlighting.light-mode.state.option.4 = Party -channel-type.wizlighting.light-mode.state.option.5 = Fireplace -channel-type.wizlighting.light-mode.state.option.6 = Cozy White -channel-type.wizlighting.light-mode.state.option.7 = Forest -channel-type.wizlighting.light-mode.state.option.8 = Pastel Colors -channel-type.wizlighting.light-mode.state.option.9 = Wakeup -channel-type.wizlighting.light-mode.state.option.10 = Bed Time -channel-type.wizlighting.light-mode.state.option.11 = Warm White -channel-type.wizlighting.light-mode.state.option.12 = Daylight -channel-type.wizlighting.light-mode.state.option.13 = Cool White -channel-type.wizlighting.light-mode.state.option.14 = Night Light -channel-type.wizlighting.light-mode.state.option.15 = Focus -channel-type.wizlighting.light-mode.state.option.16 = Relax -channel-type.wizlighting.light-mode.state.option.17 = True Colors -channel-type.wizlighting.light-mode.state.option.18 = TV Time -channel-type.wizlighting.light-mode.state.option.19 = Plant Growth -channel-type.wizlighting.light-mode.state.option.20 = Spring -channel-type.wizlighting.light-mode.state.option.21 = Summer -channel-type.wizlighting.light-mode.state.option.22 = Fall -channel-type.wizlighting.light-mode.state.option.23 = Deep Dive -channel-type.wizlighting.light-mode.state.option.24 = Jungle -channel-type.wizlighting.light-mode.state.option.25 = Mojito -channel-type.wizlighting.light-mode.state.option.26 = Club -channel-type.wizlighting.light-mode.state.option.27 = Christmas -channel-type.wizlighting.light-mode.state.option.28 = Halloween -channel-type.wizlighting.light-mode.state.option.29 = Candlelight -channel-type.wizlighting.light-mode.state.option.30 = Golden White -channel-type.wizlighting.light-mode.state.option.31 = Pulse -channel-type.wizlighting.light-mode.state.option.32 = Steampunk -channel-type.wizlighting.speed.label = Dynamic Light Mode Speed -channel-type.wizlighting.speed.description = Speed of color/intensity changes in dynamic light modes diff --git a/bundles/pom.xml b/bundles/pom.xml index 91cf7b66d0c8e..f8e41e838d9a3 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -454,7 +454,7 @@ org.openhab.binding.wemo org.openhab.binding.wifiled org.openhab.binding.windcentrale - org.openhab.binding.wizlighting + org.openhab.binding.wiz org.openhab.binding.wlanthermo org.openhab.binding.wled org.openhab.binding.wolfsmartset From 1d81603cd4123a59b806553e6c0ac8414ce7011c Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 1 Nov 2024 10:58:10 -0600 Subject: [PATCH 05/26] address new compilation warnings after SAT warnings addressed Signed-off-by: Cody Cutrer --- .../wiz/internal/enums/WizLightMode.java | 2 +- .../wiz/internal/utils/NetworkUtils.java | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java index 74ae23f40f5b0..a5f29fb379dbd 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizLightMode.java @@ -103,7 +103,7 @@ public int getSceneId() { public static @Nullable WizLightMode fromSceneName(String name) { WizLightMode r = null; - if (name != null && !"".equals(name)) { + if (!name.isEmpty()) { r = LIGHT_MODE_MAP_BY_NAME.get(name.toLowerCase().replaceAll("\\W+", "")); } return r; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java index eb3daa95d9b19..a1ec9c5e77f55 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java @@ -43,8 +43,12 @@ public final class NetworkUtils { while (networks.hasMoreElements()) { NetworkInterface network = networks.nextElement(); - if (network != null && networkMatchesIP(network, matchIP)) { - macAddress = convertBytesToMACString(network.getHardwareAddress()); + if (networkMatchesIP(network, matchIP)) { + byte[] hardwareAddress = network.getHardwareAddress(); + if (hardwareAddress == null) { + continue; + } + macAddress = convertBytesToMACString(hardwareAddress); break; // Short circuit if we found it } } @@ -52,12 +56,10 @@ public final class NetworkUtils { } private static boolean networkMatchesIP(NetworkInterface network, String ip) { - if (network != null && ip != null) { - for (InterfaceAddress interfaceAddress : network.getInterfaceAddresses()) { - String hostAddress = interfaceAddress.getAddress().getHostAddress(); - if (ip.equals(hostAddress)) { - return true; - } + for (InterfaceAddress interfaceAddress : network.getInterfaceAddresses()) { + String hostAddress = interfaceAddress.getAddress().getHostAddress(); + if (ip.equals(hostAddress)) { + return true; } } @@ -66,11 +68,9 @@ private static boolean networkMatchesIP(NetworkInterface network, String ip) { private static String convertBytesToMACString(byte[] hardwareAddress) { StringBuilder macAddressBuilder = new StringBuilder(); - if (hardwareAddress != null) { - for (int macAddressByteIndex = 0; macAddressByteIndex < hardwareAddress.length; macAddressByteIndex++) { - String macAddressHexByte = String.format("%02X", hardwareAddress[macAddressByteIndex]); - macAddressBuilder.append(macAddressHexByte); - } + for (int macAddressByteIndex = 0; macAddressByteIndex < hardwareAddress.length; macAddressByteIndex++) { + String macAddressHexByte = String.format("%02X", hardwareAddress[macAddressByteIndex]); + macAddressBuilder.append(macAddressHexByte); } return macAddressBuilder.toString(); } From 58d5c609b99d63512288511bd29e25a82521994e Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 1 Nov 2024 13:50:33 -0600 Subject: [PATCH 06/26] avoid casts after instanceof Signed-off-by: Cody Cutrer --- .../wiz/internal/handler/WizHandler.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 0eaecd8e1429b..f03d589c50407 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -129,23 +129,22 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { switch (channelUID.getId()) { case CHANNEL_COLOR: - if (command instanceof HSBType) { - handleHSBCommand((HSBType) command); - } else if (command instanceof PercentType) { - handlePercentCommand((PercentType) command); - } else if (command instanceof OnOffType) { - handleOnOffCommand((OnOffType) command); + if (command instanceof HSBType hsbCommand) { + handleHSBCommand(hsbCommand); + } else if (command instanceof PercentType percentCommand) { + handlePercentCommand(percentCommand); + } else if (command instanceof OnOffType onOffCommand) { + handleOnOffCommand(onOffCommand); } else if (command instanceof IncreaseDecreaseType) { handleIncreaseDecreaseCommand(command == IncreaseDecreaseType.INCREASE); } break; case CHANNEL_TEMPERATURE: - if (command instanceof PercentType) { - handleTemperatureCommand((PercentType) command); - } else if (command instanceof OnOffType) { - handleTemperatureCommand( - ((OnOffType) command) == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); + if (command instanceof PercentType percentCommand) { + handleTemperatureCommand(percentCommand); + } else if (command instanceof OnOffType onOffCommand) { + handleTemperatureCommand(onOffCommand == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); } else if (command instanceof IncreaseDecreaseType) { handleIncreaseDecreaseTemperatureCommand(command == IncreaseDecreaseType.INCREASE); } @@ -161,21 +160,21 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { } case CHANNEL_BRIGHTNESS: - if (command instanceof PercentType) { - handlePercentCommand((PercentType) command); - } else if (command instanceof OnOffType) { - handleOnOffCommand((OnOffType) command); + if (command instanceof PercentType percentCommand) { + handlePercentCommand(percentCommand); + } else if (command instanceof OnOffType onOffCommand) { + handleOnOffCommand(onOffCommand); } else if (command instanceof IncreaseDecreaseType) { handleIncreaseDecreaseCommand(command == IncreaseDecreaseType.INCREASE); } break; case CHANNEL_STATE: - if (command instanceof OnOffType) { + if (command instanceof OnOffType onOffCommand) { if (isFan) { - handleFanOnOffCommand((OnOffType) command); + handleFanOnOffCommand(onOffCommand); } else { - handleOnOffCommand((OnOffType) command); + handleOnOffCommand(onOffCommand); } } break; @@ -187,10 +186,10 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { case CHANNEL_SPEED: // TODO: handle fan speed - if (command instanceof PercentType) { - handleSpeedCommand((PercentType) command); - } else if (command instanceof OnOffType) { - handleSpeedCommand(((OnOffType) command) == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); + if (command instanceof PercentType percentCommand) { + handleSpeedCommand(percentCommand); + } else if (command instanceof OnOffType onOffCommand) { + handleSpeedCommand(onOffCommand == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); } else if (command instanceof IncreaseDecreaseType) { handleIncreaseDecreaseSpeedCommand(command == IncreaseDecreaseType.INCREASE); } From 51c024cfea07b39e80754fb29df11c77d0e4cdde Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Fri, 1 Nov 2024 14:35:49 -0600 Subject: [PATCH 07/26] use a dynamic state description provider for color temperature range Signed-off-by: Cody Cutrer --- .../wiz/internal/WizBindingConstants.java | 2 +- .../wiz/internal/WizHandlerFactory.java | 7 +- .../internal/WizStateDescriptionProvider.java | 73 +++++++++++++++ .../ColorTemperatureRequestParam.java | 8 -- .../internal/entities/ModelConfigResult.java | 69 ++++++++++++++ .../wiz/internal/entities/WizResponse.java | 18 +++- .../wiz/internal/entities/WizSyncState.java | 10 --- .../wiz/internal/enums/WizMethodType.java | 5 ++ .../wiz/internal/handler/WizHandler.java | 90 ++++++++++++++----- .../utils/WizResponseDeserializer.java | 11 +++ .../resources/OH-INF/thing/thing-types.xml | 16 +--- 11 files changed, 247 insertions(+), 62 deletions(-) create mode 100644 bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizStateDescriptionProvider.java create mode 100644 bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index f0879162260d6..f8c4f48c6e412 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -119,7 +119,6 @@ public class WizBindingConstants { */ public static final int MIN_COLOR_TEMPERATURE = 2200; public static final int MAX_COLOR_TEMPERATURE = 6500; - public static final int COLOR_TEMPERATURE_RANGE = MAX_COLOR_TEMPERATURE - MIN_COLOR_TEMPERATURE; // -------------- Bulb Properties ---------------- @@ -136,4 +135,5 @@ public class WizBindingConstants { public static final String EXPECTED_MODULE_NAME = "ESP01_SHRGB1C_31"; public static final String LAST_KNOWN_FIRMWARE_VERSION = "1.18.0"; + public static final String MODEL_CONFIG_MINIMUM_FIRMWARE_VERSION = "1.22"; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java index 363066d713eb0..b7342a57ddd47 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java @@ -41,10 +41,13 @@ public class WizHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(WizHandlerFactory.class); private final WizMediator mediator; + private final WizStateDescriptionProvider stateDescriptionProvider; @Activate - public WizHandlerFactory(@Reference WizMediator mediator) { + public WizHandlerFactory(@Reference WizMediator mediator, + @Reference WizStateDescriptionProvider stateDescriptionProvider) { this.mediator = mediator; + this.stateDescriptionProvider = stateDescriptionProvider; } @Override @@ -59,7 +62,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { if (supportsThingType(thing.getThingTypeUID())) { WizHandler handler; - handler = new WizHandler(thing, this.mediator.getRegistrationParams()); + handler = new WizHandler(thing, this.mediator.getRegistrationParams(), stateDescriptionProvider); mediator.registerThingAndWizBulbHandler(thing, handler); return handler; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizStateDescriptionProvider.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizStateDescriptionProvider.java new file mode 100644 index 0000000000000..9d462a7982c82 --- /dev/null +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizStateDescriptionProvider.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2010-2024 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wiz.internal; + +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.type.DynamicStateDescriptionProvider; +import org.openhab.core.types.StateDescription; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Provide a dynamic state description for color temp to define the min/max as provided by the + * actual bulb. + * This service is started on-demand only, as soon as {@link WizThingHandlerFactory} requires it. + * + * @author Cody Cutrer - Initial contribution + */ +@Component(service = { DynamicStateDescriptionProvider.class, WizStateDescriptionProvider.class }) +@NonNullByDefault +public class WizStateDescriptionProvider implements DynamicStateDescriptionProvider { + + private final Map stateDescriptions = new ConcurrentHashMap<>(); + private final Logger logger = LoggerFactory.getLogger(WizStateDescriptionProvider.class); + + /** + * Set a state description for a channel. This description will be used when preparing the channel state by + * the framework for presentation. A previous description, if existed, will be replaced. + * + * @param channelUID channel UID + * @param description state description for the channel + */ + public void setDescription(ChannelUID channelUID, StateDescription description) { + logger.debug("Adding state description for channel {}: {}", channelUID, description); + stateDescriptions.put(channelUID, description); + } + + @Override + public @Nullable StateDescription getStateDescription(Channel channel, + @Nullable StateDescription originalStateDescription, @Nullable Locale locale) { + StateDescription description = stateDescriptions.get(channel.getUID()); + if (description != null) { + logger.trace("Providing state description for channel {}", channel.getUID()); + } + return description; + } + + /** + * Removes the given channel description. + * + * @param channel The channel + */ + public void remove(ChannelUID channel) { + stateDescriptions.remove(channel); + } +} diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java index 677887de0f081..3e07c6e0c2d39 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java @@ -12,10 +12,7 @@ */ package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wiz.internal.WizBindingConstants.*; - import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.core.library.types.PercentType; import com.google.gson.annotations.Expose; @@ -38,11 +35,6 @@ public ColorTemperatureRequestParam(int temp) { this.temp = temp; } - public ColorTemperatureRequestParam(PercentType colorPercent) { - // NOTE: 0% is cold (highest K) and 100% is warm (lowest K) - temp = MAX_COLOR_TEMPERATURE - Math.round((COLOR_TEMPERATURE_RANGE * colorPercent.floatValue()) / 100); - } - public int getColorTemperature() { return temp; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java new file mode 100644 index 0000000000000..aedfd8fc786d1 --- /dev/null +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2024 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wiz.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents the "result" of one request for a bulb's model + * configuration + * + * { + * "method": "getModelConfig", "id": 1, "env":"pro", + * "result": { + * "ps":2, "pwmFreq":1000, "pwmRes":11, "pwmRange":[0,100], + * "wcr":20, "nowc":1, "cctRange": [1800,2100,2100,2100], + * "renderFactor": [120,255,255,255,0,0,20,90,255,255], "hasCctTable": 6, + * "wizc1": { + * "mode": [0,0,0,0,0,0,2100], + * "opts": { "dim": 100 } + * }, + * "wizc2": { + * "mode": [0,0,0,0,0,0,2100], + * "opts": { "dim": 50 } + * }, + * "drvIface":4, + * "i2cDrv": [ + * { + * "chip": "BP5758D", + * "addr": 255, + * "freq": 200, + * "curr": [30,30,30,36,36], + * "output":[3,2,1,4,5] + * }, { + * "chip": "NONE", + * "addr": 0, + * "freq": 0, + * "curr": [0,0,0,0,0], + * "output": [0,0,0,0,0] + * }, { + * "chip": "NONE", + * "addr": 0, + * "freq": 0, + * "curr": [0,0,0,0,0], + * "output":[0,0,0,0,0] + * } + * ] + * } + * } + * + * @author Cody Cutrer - Initial contribution + * + */ +@NonNullByDefault +public class ModelConfigResult { + @Expose(serialize = true, deserialize = true) + public int[] cctRange = {}; +} diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java index eb7a8b6b1a8ae..3c373201a2a6d 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java @@ -61,7 +61,11 @@ public class WizResponse { // The system configuration result, if present @Expose(serialize = true, deserialize = true) - private @Nullable SystemConfigResult configResult; + private @Nullable SystemConfigResult systemConfigResult; + + // The modeul configuration result, if present + @Expose(serialize = true, deserialize = true) + private @Nullable ModelConfigResult modelConfigResult; // The parameters or result of a command/response // A "result" is generally returned when solicited using a set/get method and a @@ -76,11 +80,19 @@ public class WizResponse { */ public @Nullable SystemConfigResult getSystemConfigResults() { - return this.configResult; + return this.systemConfigResult; } public void setSystemConfigResult(final SystemConfigResult configResult) { - this.configResult = configResult; + this.systemConfigResult = configResult; + } + + public @Nullable ModelConfigResult getModelConfigResults() { + return this.modelConfigResult; + } + + public void setModelConfigResult(final ModelConfigResult configResult) { + this.modelConfigResult = configResult; } public boolean getResultSuccess() { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index 0876945449552..e22409bf30dac 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -18,7 +18,6 @@ import org.openhab.binding.wiz.internal.enums.WizColorMode; import org.openhab.binding.wiz.internal.utils.WizColorConverter; import org.openhab.core.library.types.HSBType; -import org.openhab.core.library.types.PercentType; import com.google.gson.annotations.Expose; @@ -140,15 +139,6 @@ public int getTemperature() { return temp; } - public PercentType getTemperaturePercent() { - return new PercentType((temp - MIN_COLOR_TEMPERATURE) / COLOR_TEMPERATURE_RANGE * 100); - } - - public void setTemperaturePercent(PercentType colorPercent) { - // NOTE: 0% is cold (highest K) and 100% is warm (lowest K) - this.temp = MAX_COLOR_TEMPERATURE - Math.round((COLOR_TEMPERATURE_RANGE * colorPercent.floatValue()) / 100); - } - public void setTemperature(int temp) { this.temp = temp; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java index 951fa99a00d00..e8b05a1d56916 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/enums/WizMethodType.java @@ -80,6 +80,11 @@ public enum WizMethodType { */ @SerializedName("syncPilot") SyncPilot("syncPilot"), + /** + * getModelConfig - gets more details on the bulb + */ + @SerializedName("getModelConfig") + GetModelConfig("getModelConfig"), /** * getSystemConfig - gets the current system configuration - no paramters need * to be included diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index f03d589c50407..7cf42f85ead75 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -16,22 +16,27 @@ import static org.openhab.core.thing.Thing.*; import java.io.IOException; +import java.math.BigDecimal; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketTimeoutException; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.Objects; 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.binding.wiz.internal.WizStateDescriptionProvider; import org.openhab.binding.wiz.internal.config.WizDeviceConfiguration; import org.openhab.binding.wiz.internal.entities.ColorRequestParam; import org.openhab.binding.wiz.internal.entities.ColorTemperatureRequestParam; import org.openhab.binding.wiz.internal.entities.DimmingRequestParam; import org.openhab.binding.wiz.internal.entities.FanStateRequestParam; +import org.openhab.binding.wiz.internal.entities.ModelConfigResult; import org.openhab.binding.wiz.internal.entities.Param; import org.openhab.binding.wiz.internal.entities.RegistrationRequestParam; import org.openhab.binding.wiz.internal.entities.SceneRequestParam; @@ -63,6 +68,8 @@ import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.openhab.core.types.StateDescription; +import org.openhab.core.types.StateDescriptionFragmentBuilder; import org.openhab.core.types.UnDefType; import org.openhab.core.util.ColorUtil; import org.slf4j.Logger; @@ -86,11 +93,15 @@ public class WizHandler extends BaseThingHandler { private WizSyncState mostRecentState; private final WizPacketConverter converter = new WizPacketConverter(); + private final WizStateDescriptionProvider stateDescriptionProvider; + private final ChannelUID colorTempChannelUID; private @Nullable ScheduledFuture keepAliveJob; private long latestUpdate = -1; private long latestOfflineRefresh = -1; private int requestId = 0; private final boolean isFan; + private int minColorTemp = MIN_COLOR_TEMPERATURE; + private int maxColorTemp = MAX_COLOR_TEMPERATURE; private volatile boolean disposed; private volatile boolean fullyInitialized; @@ -99,12 +110,16 @@ public class WizHandler extends BaseThingHandler { * Default constructor. * * @param thing the thing of the handler. + * @param stateDescriptionProvider A state description provider */ - public WizHandler(final Thing thing, final RegistrationRequestParam registrationPacket) { + public WizHandler(final Thing thing, final RegistrationRequestParam registrationPacket, + WizStateDescriptionProvider stateDescriptionProvider) { super(thing); this.registrationInfo = registrationPacket; + this.stateDescriptionProvider = stateDescriptionProvider; this.mostRecentState = new WizSyncState(); this.isFan = thing.getThingTypeUID().equals(THING_TYPE_CEILING_FAN); + colorTempChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_TEMPERATURE_ABS); fullyInitialized = false; } @@ -142,9 +157,10 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { case CHANNEL_TEMPERATURE: if (command instanceof PercentType percentCommand) { - handleTemperatureCommand(percentCommand); + handleTemperatureCommand(percentToColorTemp(percentCommand)); } else if (command instanceof OnOffType onOffCommand) { - handleTemperatureCommand(onOffCommand == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO); + handleTemperatureCommand( + percentToColorTemp(onOffCommand == OnOffType.ON ? PercentType.HUNDRED : PercentType.ZERO)); } else if (command instanceof IncreaseDecreaseType) { handleIncreaseDecreaseTemperatureCommand(command == IncreaseDecreaseType.INCREASE); } @@ -283,26 +299,21 @@ private void handleIncreaseDecreaseCommand(boolean isIncrease) { handlePercentCommand(new PercentType(newDimming)); } - private void handleTemperatureCommand(PercentType temperature) { - setPilotCommand(new ColorTemperatureRequestParam(temperature)); - mostRecentState.setTemperaturePercent(temperature); - } - private void handleTemperatureCommand(int temperature) { setPilotCommand(new ColorTemperatureRequestParam(temperature)); mostRecentState.setTemperature(temperature); } private void handleIncreaseDecreaseTemperatureCommand(boolean isIncrease) { - int oldTempPct = mostRecentState.getTemperaturePercent().intValue(); - int newTempPct = 50; + float oldTempPct = colorTempToPercent(mostRecentState.getTemperature()).floatValue(); + float newTempPct = 50; if (isIncrease) { newTempPct = Math.min(100, oldTempPct + 5); } else { newTempPct = Math.max(0, oldTempPct - 5); } logger.debug("[{}] Changing color temperature from {}% to {}%.", config.bulbIpAddress, oldTempPct, newTempPct); - handleTemperatureCommand(new PercentType(newTempPct)); + handleTemperatureCommand(percentToColorTemp(new PercentType(BigDecimal.valueOf(newTempPct)))); } private void handleSpeedCommand(PercentType speed) { @@ -417,6 +428,8 @@ public void dispose() { keepAliveJob.cancel(true); this.keepAliveJob = null; } + stateDescriptionProvider.remove(colorTempChannelUID); + super.dispose(); } private synchronized void getPilot() { @@ -553,7 +566,7 @@ private void updateLightStatesFromParams(final WizSyncState receivedParam) { HSBType color = ColorUtil.xyToHsb(xy); updateState(CHANNEL_COLOR, new HSBType(color.getHue(), color.getSaturation(), new PercentType(receivedParam.getDimming()))); - updateState(CHANNEL_TEMPERATURE, receivedParam.getTemperaturePercent()); + updateState(CHANNEL_TEMPERATURE, colorTempToPercent(receivedParam.getTemperature())); updateState(CHANNEL_TEMPERATURE_ABS, new QuantityType<>(receivedParam.getTemperature(), Units.KELVIN)); break; @@ -676,21 +689,21 @@ private synchronized void updateBulbProperties() { } WizResponse registrationResponse = sendRequestPacket(WizMethodType.GetSystemConfig, null); if (registrationResponse != null) { - SystemConfigResult responseResult = registrationResponse.getSystemConfigResults(); - if (responseResult != null) { + SystemConfigResult systemConfigResult = registrationResponse.getSystemConfigResults(); + if (systemConfigResult != null) { // Update all the thing properties based on the result Map thingProperties = new HashMap(); thingProperties.put(PROPERTY_VENDOR, "WiZ Connected"); - thingProperties.put(PROPERTY_FIRMWARE_VERSION, responseResult.fwVersion); - thingProperties.put(PROPERTY_MAC_ADDRESS, responseResult.mac); + thingProperties.put(PROPERTY_FIRMWARE_VERSION, systemConfigResult.fwVersion); + thingProperties.put(PROPERTY_MAC_ADDRESS, systemConfigResult.mac); thingProperties.put(PROPERTY_IP_ADDRESS, registrationResponse.getWizResponseIpAddress()); - thingProperties.put(PROPERTY_HOME_ID, String.valueOf(responseResult.homeId)); - thingProperties.put(PROPERTY_ROOM_ID, String.valueOf(responseResult.roomId)); - thingProperties.put(PROPERTY_HOME_LOCK, String.valueOf(responseResult.homeLock)); - thingProperties.put(PROPERTY_PAIRING_LOCK, String.valueOf(responseResult.pairingLock)); - thingProperties.put(PROPERTY_TYPE_ID, String.valueOf(responseResult.typeId)); - thingProperties.put(PROPERTY_MODULE_NAME, responseResult.moduleName); - thingProperties.put(PROPERTY_GROUP_ID, String.valueOf(responseResult.groupId)); + thingProperties.put(PROPERTY_HOME_ID, String.valueOf(systemConfigResult.homeId)); + thingProperties.put(PROPERTY_ROOM_ID, String.valueOf(systemConfigResult.roomId)); + thingProperties.put(PROPERTY_HOME_LOCK, String.valueOf(systemConfigResult.homeLock)); + thingProperties.put(PROPERTY_PAIRING_LOCK, String.valueOf(systemConfigResult.pairingLock)); + thingProperties.put(PROPERTY_TYPE_ID, String.valueOf(systemConfigResult.typeId)); + thingProperties.put(PROPERTY_MODULE_NAME, systemConfigResult.moduleName); + thingProperties.put(PROPERTY_GROUP_ID, String.valueOf(systemConfigResult.groupId)); updateProperties(thingProperties); updateTimestamps(); } else { @@ -699,8 +712,27 @@ private synchronized void updateBulbProperties() { config.bulbIpAddress, config.bulbMacAddress); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); } + + // Firmware versions > 1.22 support more details + registrationResponse = sendRequestPacket(WizMethodType.GetModelConfig, null); + if (registrationResponse != null) { + ModelConfigResult modelConfigResult = registrationResponse.getModelConfigResults(); + if (modelConfigResult != null && modelConfigResult.cctRange.length > 0) { + minColorTemp = Arrays.stream(modelConfigResult.cctRange).min().getAsInt(); + maxColorTemp = Arrays.stream(modelConfigResult.cctRange).max().getAsInt(); + logger.warn("min temp: {} max temp: {}", minColorTemp, maxColorTemp); + StateDescription stateDescription = StateDescriptionFragmentBuilder.create() + .withMinimum(BigDecimal.valueOf(minColorTemp)).withMaximum(BigDecimal.valueOf(maxColorTemp)) + .withPattern("%.0f K").build().toStateDescription(); + stateDescriptionProvider.setDescription(colorTempChannelUID, + Objects.requireNonNull(stateDescription)); + } + } else { + // Not a big deal; probably just an older bulb + logger.warn("[{}] No response to getModelConfig request from bulb", config.bulbIpAddress); + } } else { - logger.debug("[{}] No response to registration request from bulb at {}", config.bulbIpAddress, + logger.debug("[{}] No response to getSystemConfig request from bulb at {}", config.bulbIpAddress, config.bulbMacAddress); // Not calling it "gone" because it's probably just been powered off and will beback any time updateStatus(ThingStatus.OFFLINE); @@ -739,6 +771,16 @@ private boolean hasConfigurationError() { && statusInfo.getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR; } + private int percentToColorTemp(PercentType command) { + int range = maxColorTemp - minColorTemp; + // NOTE: 0% is cold (highest K) and 100% is warm (lowest K) + return maxColorTemp - Math.round((range * command.floatValue()) / 100); + } + + private PercentType colorTempToPercent(int temp) { + return new PercentType(BigDecimal.valueOf((float) temp - minColorTemp / (maxColorTemp - minColorTemp) * 100)); + } + // SETTERS AND GETTERS public String getBulbIpAddress() { return config.bulbIpAddress; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java index 66f6cdbcd0d61..4ebf3d3e7b280 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java @@ -19,6 +19,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.wiz.internal.entities.ErrorResponseResult; +import org.openhab.binding.wiz.internal.entities.ModelConfigResult; import org.openhab.binding.wiz.internal.entities.SystemConfigResult; import org.openhab.binding.wiz.internal.entities.WizResponse; import org.openhab.binding.wiz.internal.entities.WizSyncState; @@ -148,6 +149,16 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf logger.trace("firstBeat result deserialized with mac {}", parsedFBParams.mac); break; + case GetModelConfig: + if (!jobject.has("result")) { + throw new JsonParseException("getModelConfig received, but no result object present"); + } + ModelConfigResult parsedMResult = context.deserialize(jobject.getAsJsonObject("result"), + ModelConfigResult.class); + deserializedResponse.setResultSucess(true); + deserializedResponse.setModelConfigResult(parsedMResult); + break; + case GetSystemConfig: // {"method": "getSystemConfig", "id": 22, "env": "pro", // "result": {"mac": "theBulbMacAddress", "homeId": xxxxxx, "roomId": xxxxxx, diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 614b79e7fd053..3449dfa76cf52 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -11,7 +11,7 @@ - + @@ -27,7 +27,7 @@ - + @@ -137,16 +137,4 @@ - - Number:Temperature - - Controls the color temperature of the light in Kelvin - ColorLight - - Control - ColorTemperature - - - - From bd6eea44a4a8217f7271625a66b5160429b6caf2 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 4 Nov 2024 09:02:31 -0700 Subject: [PATCH 08/26] apply review suggestions Signed-off-by: Cody Cutrer --- bundles/org.openhab.binding.wiz/README.md | 2 +- .../binding/wiz/internal/WizBindingConstants.java | 4 +--- .../binding/wiz/internal/WizHandlerFactory.java | 9 +++++++-- .../wiz/internal/config/WizDeviceConfiguration.java | 4 ++-- .../binding/wiz/internal/entities/WizResponse.java | 2 +- .../binding/wiz/internal/handler/WizHandler.java | 13 +++++++++---- .../wiz/internal/handler/WizMediatorImpl.java | 2 +- .../src/main/resources/OH-INF/thing/thing-types.xml | 1 + 8 files changed, 23 insertions(+), 14 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/README.md b/bundles/org.openhab.binding.wiz/README.md index 1c875457bb05f..81cd3bb11278a 100644 --- a/bundles/org.openhab.binding.wiz/README.md +++ b/bundles/org.openhab.binding.wiz/README.md @@ -1,4 +1,4 @@ -![logo](https://www.wizconnected.com/content/dam/wiz/master/logo-wiz-black-navigation.svg) +# WiZ Binding This binding integrates [WiZ Connected](https://www.wizconnected.com/en-US/) smart devices. These inexpensive devices, typically smart bulbs, are available online and in most Home Depot stores. diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index f8c4f48c6e412..c43c5b3a17609 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -58,7 +58,7 @@ public class WizBindingConstants { public static final String CHANNEL_LAST_UPDATE = "last-update"; public static final String CHANNEL_MODE = "mode"; public static final String CHANNEL_REVERSE = "reverse"; - public static final String CHANNEL_RSSI = "signal-strength"; + public static final String CHANNEL_SIGNAL_STRING = "signal-strength"; public static final String CHANNEL_SPEED = "speed"; public static final String CHANNEL_STATE = "state"; public static final String CHANNEL_TEMPERATURE = "temperature"; @@ -75,7 +75,6 @@ public class WizBindingConstants { * Host address configuration argument key. */ public static final String CONFIG_IP_ADDRESS = "bulbIpAddress"; - public static final String MISSING_INVALID_IP_ADDRESS = "bulbIpAddress"; /** * Wifi socket update interval configuration argument key. @@ -122,7 +121,6 @@ public class WizBindingConstants { // -------------- Bulb Properties ---------------- - public static final String PROPERTY_BINDING_VERSION = "bindingVersion"; public static final String PROPERTY_IP_ADDRESS = "ipAddress"; public static final String PROPERTY_HOME_ID = "homeId"; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java index b7342a57ddd47..79fa4e67c7806 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java @@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.wiz.internal.handler.WizHandler; import org.openhab.binding.wiz.internal.handler.WizMediator; +import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.BaseThingHandlerFactory; @@ -42,12 +43,15 @@ public class WizHandlerFactory extends BaseThingHandlerFactory { private final WizMediator mediator; private final WizStateDescriptionProvider stateDescriptionProvider; + private final TimeZoneProvider timeZoneProvider; @Activate public WizHandlerFactory(@Reference WizMediator mediator, - @Reference WizStateDescriptionProvider stateDescriptionProvider) { + @Reference WizStateDescriptionProvider stateDescriptionProvider, + @Reference TimeZoneProvider timeZoneProvider) { this.mediator = mediator; this.stateDescriptionProvider = stateDescriptionProvider; + this.timeZoneProvider = timeZoneProvider; } @Override @@ -62,7 +66,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { if (supportsThingType(thing.getThingTypeUID())) { WizHandler handler; - handler = new WizHandler(thing, this.mediator.getRegistrationParams(), stateDescriptionProvider); + handler = new WizHandler(thing, this.mediator.getRegistrationParams(), stateDescriptionProvider, + timeZoneProvider); mediator.registerThingAndWizBulbHandler(thing, handler); return handler; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java index 2de79930f1a41..dcecb97a329b8 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java @@ -26,10 +26,10 @@ public class WizDeviceConfiguration { /** - * Configuration for a Bond Bridge or Device + * Configuration for a WiZ Device */ public String bulbMacAddress = MISSING_INVALID_MAC_ADDRESS; - public String bulbIpAddress = MISSING_INVALID_IP_ADDRESS; + public String bulbIpAddress = ""; public long updateInterval = DEFAULT_REFRESH_INTERVAL_SEC; public boolean useHeartBeats = false; // true: register to get 5s heart-beats public long reconnectInterval = DEFAULT_RECONNECT_INTERVAL_MIN; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java index 3c373201a2a6d..fb810df7a3664 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java @@ -31,7 +31,7 @@ public class WizResponse { // The IP address we're coming from @Expose(serialize = false, deserialize = true) - private String wizResponseIpAddress = MISSING_INVALID_IP_ADDRESS; + private String wizResponseIpAddress = ""; // Increasing numeric value. // Bulb doesn't seem to care if it receives the same id multiple time diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 7cf42f85ead75..aabab9a3767bd 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -21,6 +21,7 @@ import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketTimeoutException; +import java.time.ZonedDateTime; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -51,6 +52,7 @@ import org.openhab.binding.wiz.internal.utils.ValidationUtils; import org.openhab.binding.wiz.internal.utils.WizPacketConverter; import org.openhab.core.config.core.Configuration; +import org.openhab.core.i18n.TimeZoneProvider; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; @@ -94,6 +96,7 @@ public class WizHandler extends BaseThingHandler { private final WizPacketConverter converter = new WizPacketConverter(); private final WizStateDescriptionProvider stateDescriptionProvider; + private final TimeZoneProvider timeZoneProvider; private final ChannelUID colorTempChannelUID; private @Nullable ScheduledFuture keepAliveJob; private long latestUpdate = -1; @@ -113,10 +116,11 @@ public class WizHandler extends BaseThingHandler { * @param stateDescriptionProvider A state description provider */ public WizHandler(final Thing thing, final RegistrationRequestParam registrationPacket, - WizStateDescriptionProvider stateDescriptionProvider) { + WizStateDescriptionProvider stateDescriptionProvider, TimeZoneProvider timeZoneProvider) { super(thing); this.registrationInfo = registrationPacket; this.stateDescriptionProvider = stateDescriptionProvider; + this.timeZoneProvider = timeZoneProvider; this.mostRecentState = new WizSyncState(); this.isFan = thing.getThingTypeUID().equals(THING_TYPE_CEILING_FAN); colorTempChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_TEMPERATURE_ABS); @@ -467,7 +471,7 @@ public synchronized void newReceivedResponseMessage(final WizResponse receivedMe // Check if the bulb still has the same IP address it had previously // If not, we need to update the configuration for the thing. - if (!receivedMessage.getWizResponseIpAddress().equals(MISSING_INVALID_IP_ADDRESS) + if (!receivedMessage.getWizResponseIpAddress().isEmpty() && !receivedMessage.getWizResponseIpAddress().equals(this.getBulbIpAddress())) { // get the old config Configuration priorConfig = getConfig(); @@ -531,7 +535,7 @@ private synchronized void updateStatesFromParams(final WizSyncState receivedPara } else { strength = 4; } - updateState(CHANNEL_RSSI, new DecimalType(strength)); + updateState(CHANNEL_SIGNAL_STRING, new DecimalType(strength)); } } @@ -677,7 +681,8 @@ private synchronized void updateTimestamps() { updateStatus(ThingStatus.ONLINE); latestUpdate = System.currentTimeMillis(); latestOfflineRefresh = System.currentTimeMillis(); - updateState(CHANNEL_LAST_UPDATE, new DateTimeType()); + final ZonedDateTime zonedDateTime = ZonedDateTime.now(timeZoneProvider.getTimeZone()); + updateState(CHANNEL_LAST_UPDATE, new DateTimeType(zonedDateTime)); } /** diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java index 1f427b63d9d43..567273424e923 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java @@ -104,7 +104,7 @@ public void processReceivedPacket(final WizResponse receivedMessage) { if (handler != null) { // deliver message to handler. handler.newReceivedResponseMessage(receivedMessage); - } else if (!bulbIp.equals(MISSING_INVALID_IP_ADDRESS)) { + } else if (!bulbIp.isEmpty()) { logger.debug("There is no handler registered for mac address: {}", receivedMessage.getWizResponseMacAddress()); WizDiscoveryService discoveryServe = this.wizDiscoveryService; diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 3449dfa76cf52..10412a5297313 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -134,6 +134,7 @@ DateTime Timestamp of last status update + Time From 4037f526caf768c27a54c0a9e94d359b7c39cb20 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 4 Nov 2024 09:42:02 -0700 Subject: [PATCH 09/26] support fans-with-lights by putting light and fan channels into groups. default discovery will detect fans as a fan-with-light, just like the WiZ app. a fan-only device will have to be manually created Signed-off-by: Cody Cutrer --- .../wiz/internal/WizBindingConstants.java | 15 ++- .../discovery/WizDiscoveryService.java | 2 +- .../wiz/internal/handler/WizHandler.java | 120 ++++++++++++------ .../main/resources/OH-INF/i18n/wiz.properties | 24 +++- .../resources/OH-INF/thing/thing-types.xml | 41 +++++- 5 files changed, 150 insertions(+), 52 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index c43c5b3a17609..17999c1e859ad 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -41,13 +41,16 @@ public class WizBindingConstants { public static final ThingTypeUID THING_TYPE_TUNABLE_BULB = new ThingTypeUID(BINDING_ID, "tunable-bulb"); public static final ThingTypeUID THING_TYPE_DIMMABLE_BULB = new ThingTypeUID(BINDING_ID, "dimmable-bulb"); public static final ThingTypeUID THING_TYPE_SMART_PLUG = new ThingTypeUID(BINDING_ID, "plug"); - public static final ThingTypeUID THING_TYPE_CEILING_FAN = new ThingTypeUID(BINDING_ID, "ceiling-fan"); + public static final ThingTypeUID THING_TYPE_FAN = new ThingTypeUID(BINDING_ID, "fan"); + public static final ThingTypeUID THING_TYPE_FAN_WITH_DIMMABLE_BULB = new ThingTypeUID(BINDING_ID, + "fan-with-dimmable-bulb"); /** * The supported thing types. */ - public static final Set SUPPORTED_THING_TYPES = Stream.of(THING_TYPE_COLOR_BULB, - THING_TYPE_TUNABLE_BULB, THING_TYPE_DIMMABLE_BULB, THING_TYPE_SMART_PLUG, THING_TYPE_CEILING_FAN) + public static final Set SUPPORTED_THING_TYPES = Stream + .of(THING_TYPE_COLOR_BULB, THING_TYPE_TUNABLE_BULB, THING_TYPE_DIMMABLE_BULB, THING_TYPE_SMART_PLUG, + THING_TYPE_FAN, THING_TYPE_FAN_WITH_DIMMABLE_BULB) .collect(Collectors.toSet()); /** @@ -58,12 +61,16 @@ public class WizBindingConstants { public static final String CHANNEL_LAST_UPDATE = "last-update"; public static final String CHANNEL_MODE = "mode"; public static final String CHANNEL_REVERSE = "reverse"; - public static final String CHANNEL_SIGNAL_STRING = "signal-strength"; + public static final String CHANNEL_SIGNAL_STRENGTH = "signal-strength"; public static final String CHANNEL_SPEED = "speed"; public static final String CHANNEL_STATE = "state"; public static final String CHANNEL_TEMPERATURE = "temperature"; public static final String CHANNEL_TEMPERATURE_ABS = "temperature-abs"; + public static final String CHANNEL_GROUP_DEVICE = "device"; + public static final String CHANNEL_GROUP_LIGHT = "light"; + public static final String CHANNEL_GROUP_FAN = "fan"; + // -------------- Configuration arguments ---------------- /** * Mac address configuration argument key. diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java index 87d56fda698e9..08afefbaf22ae 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java @@ -194,7 +194,7 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd // Check for "FANDIMS" as in confirmed example ESP03_FANDIMS_31 for Faro Barcelona Smart Fan } else if (discoveredModel.contains("FANDIMS")) { - thisBulbType = THING_TYPE_CEILING_FAN; + thisBulbType = THING_TYPE_FAN; thisBulbLabel = "WiZ Smart Fan at " + lightIpAddress; newThingId = new ThingUID(thisBulbType, lightMacAddress); logger.trace("New device appears to be a smart fan and will be given the UUID: {}", newThingId); diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index aabab9a3767bd..89695a2997058 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -70,6 +70,7 @@ import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.openhab.core.types.State; import org.openhab.core.types.StateDescription; import org.openhab.core.types.StateDescriptionFragmentBuilder; import org.openhab.core.types.UnDefType; @@ -103,6 +104,7 @@ public class WizHandler extends BaseThingHandler { private long latestOfflineRefresh = -1; private int requestId = 0; private final boolean isFan; + private final boolean isFanOnly; private int minColorTemp = MIN_COLOR_TEMPERATURE; private int maxColorTemp = MAX_COLOR_TEMPERATURE; @@ -122,7 +124,9 @@ public WizHandler(final Thing thing, final RegistrationRequestParam registration this.stateDescriptionProvider = stateDescriptionProvider; this.timeZoneProvider = timeZoneProvider; this.mostRecentState = new WizSyncState(); - this.isFan = thing.getThingTypeUID().equals(THING_TYPE_CEILING_FAN); + this.isFan = thing.getThingTypeUID().equals(THING_TYPE_FAN) + || thing.getThingTypeUID().equals(THING_TYPE_FAN_WITH_DIMMABLE_BULB); + this.isFanOnly = thing.getThingTypeUID().equals(THING_TYPE_FAN); colorTempChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_TEMPERATURE_ABS); fullyInitialized = false; } @@ -146,7 +150,15 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { return; } - switch (channelUID.getId()) { + if (isFanOnly || (isFan && CHANNEL_GROUP_FAN.equals(channelUID.getGroupId()))) { + handleFanCommand(channelUID.getIdWithoutGroup(), command); + } else if (!isFan || (isFan && CHANNEL_GROUP_LIGHT.equals(channelUID.getGroupId()))) { + handleLightCommand(channelUID.getIdWithoutGroup(), command); + } + } + + private void handleLightCommand(final String channelId, final Command command) { + switch (channelId) { case CHANNEL_COLOR: if (command instanceof HSBType hsbCommand) { handleHSBCommand(hsbCommand); @@ -158,7 +170,6 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { handleIncreaseDecreaseCommand(command == IncreaseDecreaseType.INCREASE); } break; - case CHANNEL_TEMPERATURE: if (command instanceof PercentType percentCommand) { handleTemperatureCommand(percentToColorTemp(percentCommand)); @@ -169,7 +180,6 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { handleIncreaseDecreaseTemperatureCommand(command == IncreaseDecreaseType.INCREASE); } break; - case CHANNEL_TEMPERATURE_ABS: QuantityType kelvinQt; if (command instanceof QuantityType commandQt @@ -178,7 +188,6 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { } else { handleTemperatureCommand(Integer.valueOf(command.toString())); } - case CHANNEL_BRIGHTNESS: if (command instanceof PercentType percentCommand) { handlePercentCommand(percentCommand); @@ -188,24 +197,15 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { handleIncreaseDecreaseCommand(command == IncreaseDecreaseType.INCREASE); } break; - case CHANNEL_STATE: if (command instanceof OnOffType onOffCommand) { - if (isFan) { - handleFanOnOffCommand(onOffCommand); - } else { - handleOnOffCommand(onOffCommand); - } + handleOnOffCommand(onOffCommand); } break; - case CHANNEL_MODE: - // TODO: handle fan mode handleLightModeCommand(command); break; - case CHANNEL_SPEED: - // TODO: handle fan speed if (command instanceof PercentType percentCommand) { handleSpeedCommand(percentCommand); } else if (command instanceof OnOffType onOffCommand) { @@ -214,7 +214,22 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { handleIncreaseDecreaseSpeedCommand(command == IncreaseDecreaseType.INCREASE); } break; + } + } + private void handleFanCommand(final String channelId, final Command command) { + switch (channelId) { + case CHANNEL_STATE: + if (command instanceof OnOffType onOffCommand) { + handleFanOnOffCommand(onOffCommand); + } + break; + case CHANNEL_MODE: + // TODO: handle fan mode + break; + case CHANNEL_SPEED: + // TODO: handle fan speed + break; case CHANNEL_REVERSE: // TODO: handle fan direction break; @@ -517,7 +532,8 @@ private synchronized void updateStatesFromParams(final WizSyncState receivedPara if (isFan) { updateFanStatesFromParams(receivedParam); - } else { + } + if (!isFanOnly) { updateLightStatesFromParams(receivedParam); } @@ -535,7 +551,7 @@ private synchronized void updateStatesFromParams(final WizSyncState receivedPara } else { strength = 4; } - updateState(CHANNEL_SIGNAL_STRING, new DecimalType(strength)); + updateDeviceState(CHANNEL_SIGNAL_STRENGTH, new DecimalType(strength)); } } @@ -546,14 +562,14 @@ private synchronized void updateStatesFromParams(final WizSyncState receivedPara */ private void updateLightStatesFromParams(final WizSyncState receivedParam) { if (!receivedParam.state) { - updateState(CHANNEL_COLOR, HSBType.BLACK); - updateState(CHANNEL_BRIGHTNESS, PercentType.ZERO); - updateState(CHANNEL_STATE, OnOffType.OFF); - updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); - updateState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); + updateLightState(CHANNEL_COLOR, HSBType.BLACK); + updateLightState(CHANNEL_BRIGHTNESS, PercentType.ZERO); + updateLightState(CHANNEL_STATE, OnOffType.OFF); + updateLightState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); + updateLightState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); } else { - updateState(CHANNEL_BRIGHTNESS, new PercentType(receivedParam.dimming)); - updateState(CHANNEL_STATE, OnOffType.ON); + updateLightState(CHANNEL_BRIGHTNESS, new PercentType(receivedParam.dimming)); + updateLightState(CHANNEL_STATE, OnOffType.ON); switch (receivedParam.getColorMode()) { case RGBMode: logger.trace( @@ -561,30 +577,30 @@ private void updateLightStatesFromParams(final WizSyncState receivedParam) { config.bulbIpAddress, receivedParam.r, receivedParam.g, receivedParam.b, receivedParam.w, receivedParam.c, receivedParam.dimming, receivedParam.getHSBColor()); - updateState(CHANNEL_COLOR, receivedParam.getHSBColor()); - updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); - updateState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); + updateLightState(CHANNEL_COLOR, receivedParam.getHSBColor()); + updateLightState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); + updateLightState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); break; case CTMode: double[] xy = ColorUtil.kelvinToXY(receivedParam.getTemperature()); HSBType color = ColorUtil.xyToHsb(xy); - updateState(CHANNEL_COLOR, new HSBType(color.getHue(), color.getSaturation(), + updateLightState(CHANNEL_COLOR, new HSBType(color.getHue(), color.getSaturation(), new PercentType(receivedParam.getDimming()))); - updateState(CHANNEL_TEMPERATURE, colorTempToPercent(receivedParam.getTemperature())); - updateState(CHANNEL_TEMPERATURE_ABS, + updateLightState(CHANNEL_TEMPERATURE, colorTempToPercent(receivedParam.getTemperature())); + updateLightState(CHANNEL_TEMPERATURE_ABS, new QuantityType<>(receivedParam.getTemperature(), Units.KELVIN)); break; case SingleColorMode: - updateState(CHANNEL_COLOR, new HSBType(DecimalType.ZERO, PercentType.ZERO, + updateLightState(CHANNEL_COLOR, new HSBType(DecimalType.ZERO, PercentType.ZERO, new PercentType(receivedParam.getDimming()))); - updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); - updateState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); + updateLightState(CHANNEL_TEMPERATURE, UnDefType.UNDEF); + updateLightState(CHANNEL_TEMPERATURE_ABS, UnDefType.UNDEF); break; } } - updateState(CHANNEL_MODE, new StringType(String.valueOf(receivedParam.sceneId))); - updateState(CHANNEL_SPEED, new PercentType(receivedParam.speed)); + updateLightState(CHANNEL_MODE, new StringType(String.valueOf(receivedParam.sceneId))); + updateLightState(CHANNEL_SPEED, new PercentType(receivedParam.speed)); } /** @@ -593,10 +609,10 @@ private void updateLightStatesFromParams(final WizSyncState receivedParam) { * @param receivedParam The received {@link WizSyncState} */ private void updateFanStatesFromParams(final WizSyncState receivedParam) { - updateState(CHANNEL_STATE, new DecimalType(receivedParam.fanState)); - updateState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); - updateState(CHANNEL_REVERSE, new DecimalType(receivedParam.fanRevrs)); - updateState(CHANNEL_MODE, new DecimalType(receivedParam.fanMode)); + updateFanState(CHANNEL_STATE, new DecimalType(receivedParam.fanState)); + updateFanState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); + updateFanState(CHANNEL_REVERSE, new DecimalType(receivedParam.fanRevrs)); + updateFanState(CHANNEL_MODE, new DecimalType(receivedParam.fanMode)); } /** @@ -682,7 +698,7 @@ private synchronized void updateTimestamps() { latestUpdate = System.currentTimeMillis(); latestOfflineRefresh = System.currentTimeMillis(); final ZonedDateTime zonedDateTime = ZonedDateTime.now(timeZoneProvider.getTimeZone()); - updateState(CHANNEL_LAST_UPDATE, new DateTimeType(zonedDateTime)); + updateDeviceState(CHANNEL_LAST_UPDATE, new DateTimeType(zonedDateTime)); } /** @@ -798,4 +814,28 @@ public String getBulbMacAddress() { public int getHomeId() { return homeId; } + + private void updateLightState(String channelId, State state) { + if (isFan) { + updateState(new ChannelUID(this.getThing().getUID(), CHANNEL_GROUP_LIGHT, channelId), state); + } else { + updateState(channelId, state); + } + } + + private void updateFanState(String channelId, State state) { + if (isFanOnly) { + updateState(channelId, state); + } else { + updateState(new ChannelUID(this.getThing().getUID(), CHANNEL_GROUP_LIGHT, channelId), state); + } + } + + private void updateDeviceState(String channelId, State state) { + if (isFan && !isFanOnly) { + updateState(new ChannelUID(this.getThing().getUID(), CHANNEL_GROUP_DEVICE, channelId), state); + } else { + updateState(channelId, state); + } + } } diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties index 017a3fbe26fe0..45a03639fc85b 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties @@ -5,12 +5,14 @@ addon.wiz.description = Binding for WiZ smart devices. # thing types -thing-type.wiz.ceiling-fan.label = WiZ Ceiling Fan -thing-type.wiz.ceiling-fan.description = Supports WiZ Ceiling Fans thing-type.wiz.color-bulb.label = WiZ Color Bulb thing-type.wiz.color-bulb.description = Supports WiZ Full Color with Tunable White Bulbs thing-type.wiz.dimmable-bulb.label = WiZ Dimmable Bulb thing-type.wiz.dimmable-bulb.description = Supports WiZ Single Color Dimmable Bulbs +thing-type.wiz.fan-with-dimmable-bulb.label = WiZ Ceiling Fan With Dimmable Bulb +thing-type.wiz.fan-with-dimmable-bulb.description = Supports WiZ Ceiling Fans With a Dimmable Bulb +thing-type.wiz.fan.label = WiZ Ceiling Fan +thing-type.wiz.fan.description = Supports WiZ Ceiling Fans thing-type.wiz.plug.label = WiZ Smart Plug thing-type.wiz.plug.description = Supports WiZ Smart Plugs thing-type.wiz.tunable-bulb.label = WiZ Tunable Bulb @@ -29,10 +31,14 @@ thing-type.config.wiz.light.updateInterval.description = Update time interval in thing-type.config.wiz.light.useHeartBeats.label = Use Heartbeats thing-type.config.wiz.light.useHeartBeats.description = True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. +# channel group types + +channel-group-type.wiz.device-channels.label = Device +channel-group-type.wiz.dimmable-light.label = Light +channel-group-type.wiz.fan-group.label = Fan + # channel types -channel-type.wiz.color-temperature-abs.label = Color Temperature -channel-type.wiz.color-temperature-abs.description = Controls the color temperature of the light in Kelvin channel-type.wiz.last-update.label = Last Update channel-type.wiz.last-update.description = Timestamp of last status update channel-type.wiz.light-mode.label = Light Mode @@ -70,3 +76,13 @@ channel-type.wiz.light-mode.state.option.31 = Pulse channel-type.wiz.light-mode.state.option.32 = Steampunk channel-type.wiz.speed.label = Dynamic Light Mode Speed channel-type.wiz.speed.description = Speed of color/intensity changes in dynamic light modes + +# thing types + +thing-type.wiz.ceiling-fan.label = WiZ Ceiling Fan +thing-type.wiz.ceiling-fan.description = Supports WiZ Ceiling Fans + +# channel types + +channel-type.wiz.color-temperature-abs.label = Color Temperature +channel-type.wiz.color-temperature-abs.description = Controls the color temperature of the light in Kelvin diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 10412a5297313..5599997747fcc 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -28,7 +28,7 @@ - + @@ -43,7 +43,7 @@ Supports WiZ Single Color Dimmable Bulbs - + @@ -66,7 +66,7 @@ - + Supports WiZ Ceiling Fans @@ -76,6 +76,18 @@ + + + Supports WiZ Ceiling Fans With a Dimmable Bulb + + + + + + + + + String @@ -138,4 +150,27 @@ + + + + + + + + + + + + + + + + + + + + + + + From 6e78154666156852312edfc2309b944f39af039e Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 4 Nov 2024 10:06:10 -0700 Subject: [PATCH 10/26] support fan speed, reverse, and mode channels Signed-off-by: Cody Cutrer --- .../entities/FanModeRequestParam.java | 40 +++++++++++++++++ .../entities/FanReverseRequestParam.java | 40 +++++++++++++++++ .../entities/FanSpeedRequestParam.java | 40 +++++++++++++++++ .../entities/FanStateRequestParam.java | 8 ++-- .../wiz/internal/entities/WizSyncState.java | 6 +-- .../wiz/internal/handler/WizHandler.java | 42 ++++++++++++++---- .../main/resources/OH-INF/i18n/wiz.properties | 12 +++++ .../resources/OH-INF/thing/thing-types.xml | 44 ++++++++++++++++--- 8 files changed, 211 insertions(+), 21 deletions(-) create mode 100644 bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java create mode 100644 bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java create mode 100644 bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java new file mode 100644 index 0000000000000..b4aa01dae9634 --- /dev/null +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2024 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wiz.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Fan Reverse Request Param + * + * @author Cody Cutrer - Initial Contribution + */ +@NonNullByDefault +public class FanModeRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private boolean fanMode; // true = 1, false = 0 + + public FanModeRequestParam(boolean fanMode) { + this.fanMode = fanMode; + } + + public boolean getFanMode() { + return fanMode; + } + + public void setFanMode(boolean fanMode) { + this.fanMode = fanMode; + } +} diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java new file mode 100644 index 0000000000000..be27426c57937 --- /dev/null +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2024 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wiz.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Fan Reverse Request Param + * + * @author Cody Cutrer - Initial Contribution + */ +@NonNullByDefault +public class FanReverseRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private boolean fanRevrs; // true = 1, false = 0 + + public FanReverseRequestParam(boolean reverse) { + this.fanRevrs = reverse; + } + + public boolean getReverse() { + return fanRevrs; + } + + public void setReverse(boolean reverse) { + this.fanRevrs = reverse; + } +} diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java new file mode 100644 index 0000000000000..3642b1e6b8e98 --- /dev/null +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2024 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 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.wiz.internal.entities; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.Expose; + +/** + * This POJO represents Fan Speed Request Param + * + * @author Cody Cutrer - Initial Contribution + */ +@NonNullByDefault +public class FanSpeedRequestParam implements Param { + @Expose(serialize = true, deserialize = true) + private int fanSpeed; // 0-6 + + public FanSpeedRequestParam(int fanSpeed) { + this.fanSpeed = fanSpeed; + } + + public int getFanSpeed() { + return fanSpeed; + } + + public void setFanSpeed(int fanSpeed) { + this.fanSpeed = fanSpeed; + } +} diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java index 6978124ef85a0..e7471654e1b29 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java @@ -24,17 +24,17 @@ @NonNullByDefault public class FanStateRequestParam implements Param { @Expose(serialize = true, deserialize = true) - private int fanState; // true = 1, false = 0 + private boolean fanState; // true = 1, false = 0 - public FanStateRequestParam(int fanState) { + public FanStateRequestParam(boolean fanState) { this.fanState = fanState; } - public int getFanState() { + public boolean getFanState() { return fanState; } - public void setFanState(int fanState) { + public void setFanState(boolean fanState) { this.fanState = fanState; } } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index e22409bf30dac..d2f3d889980a6 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -95,13 +95,13 @@ public class WizSyncState { public int schdPsetId; @Expose(serialize = true, deserialize = true) - public int fanState; + public boolean fanState; @Expose(serialize = true, deserialize = true) public int fanSpeed; @Expose(serialize = true, deserialize = true) - public int fanMode; + public boolean fanMode; @Expose(serialize = true, deserialize = true) - public int fanRevrs; + public boolean fanRevrs; public WizColorMode getColorMode() { if (r != 0 || g != 0 || b != 0) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 89695a2997058..0da0e59a2f999 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -36,6 +36,9 @@ import org.openhab.binding.wiz.internal.entities.ColorRequestParam; import org.openhab.binding.wiz.internal.entities.ColorTemperatureRequestParam; import org.openhab.binding.wiz.internal.entities.DimmingRequestParam; +import org.openhab.binding.wiz.internal.entities.FanModeRequestParam; +import org.openhab.binding.wiz.internal.entities.FanReverseRequestParam; +import org.openhab.binding.wiz.internal.entities.FanSpeedRequestParam; import org.openhab.binding.wiz.internal.entities.FanStateRequestParam; import org.openhab.binding.wiz.internal.entities.ModelConfigResult; import org.openhab.binding.wiz.internal.entities.Param; @@ -225,13 +228,19 @@ private void handleFanCommand(final String channelId, final Command command) { } break; case CHANNEL_MODE: - // TODO: handle fan mode + if (command instanceof OnOffType onOffCommand) { + handleFanModeCommand(onOffCommand); + } break; case CHANNEL_SPEED: - // TODO: handle fan speed + if (command instanceof DecimalType numberCommand) { + handleFanSpeedCommand(numberCommand); + } break; case CHANNEL_REVERSE: - // TODO: handle fan direction + if (command instanceof OnOffType onOffCommand) { + handleFanReverseCommand(onOffCommand); + } break; } } @@ -297,13 +306,28 @@ private void handlePercentCommand(PercentType brightness) { } private void handleOnOffCommand(OnOffType onOff) { - setPilotCommand(new StateRequestParam(onOff == OnOffType.ON ? true : false)); + setPilotCommand(new StateRequestParam(onOff == OnOffType.ON)); mostRecentState.state = onOff == OnOffType.ON; } private void handleFanOnOffCommand(OnOffType onOff) { - setPilotCommand(new FanStateRequestParam(onOff == OnOffType.ON ? 1 : 0)); - mostRecentState.state = onOff == OnOffType.ON; + setPilotCommand(new FanStateRequestParam(onOff == OnOffType.ON)); + mostRecentState.fanState = onOff == OnOffType.ON; + } + + private void handleFanSpeedCommand(DecimalType speed) { + setPilotCommand(new FanSpeedRequestParam(speed.intValue())); + mostRecentState.fanSpeed = speed.intValue(); + } + + private void handleFanReverseCommand(OnOffType onOff) { + setPilotCommand(new FanReverseRequestParam(onOff == OnOffType.ON)); + mostRecentState.fanRevrs = onOff == OnOffType.ON; + } + + private void handleFanModeCommand(OnOffType onOff) { + setPilotCommand(new FanModeRequestParam(onOff == OnOffType.ON)); + mostRecentState.fanMode = onOff == OnOffType.ON; } private void handleIncreaseDecreaseCommand(boolean isIncrease) { @@ -609,10 +633,10 @@ private void updateLightStatesFromParams(final WizSyncState receivedParam) { * @param receivedParam The received {@link WizSyncState} */ private void updateFanStatesFromParams(final WizSyncState receivedParam) { - updateFanState(CHANNEL_STATE, new DecimalType(receivedParam.fanState)); + updateFanState(CHANNEL_STATE, OnOffType.from(receivedParam.fanState)); updateFanState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); - updateFanState(CHANNEL_REVERSE, new DecimalType(receivedParam.fanRevrs)); - updateFanState(CHANNEL_MODE, new DecimalType(receivedParam.fanMode)); + updateFanState(CHANNEL_REVERSE, OnOffType.from(receivedParam.fanRevrs)); + updateFanState(CHANNEL_MODE, OnOffType.from(receivedParam.fanMode)); } /** diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties index 45a03639fc85b..a86cb4546af04 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties @@ -39,8 +39,17 @@ channel-group-type.wiz.fan-group.label = Fan # channel types +channel-type.wiz.fan-mode.label = Mode +channel-type.wiz.fan-mode.state.option.OFF = Normal +channel-type.wiz.fan-mode.state.option.ON = Breeze +channel-type.wiz.fan-reverse.label = Reverse +channel-type.wiz.fan-reverse.state.option.OFF = Forward +channel-type.wiz.fan-reverse.state.option.ON = Reverse +channel-type.wiz.fan-speed.label = Fan Speed channel-type.wiz.last-update.label = Last Update channel-type.wiz.last-update.description = Timestamp of last status update +channel-type.wiz.light-mode-speed.label = Dynamic Light Mode Speed +channel-type.wiz.light-mode-speed.description = Speed of color/intensity changes in dynamic light modes channel-type.wiz.light-mode.label = Light Mode channel-type.wiz.light-mode.state.option.1 = Ocean channel-type.wiz.light-mode.state.option.2 = Romance @@ -74,6 +83,9 @@ channel-type.wiz.light-mode.state.option.29 = Candlelight channel-type.wiz.light-mode.state.option.30 = Golden White channel-type.wiz.light-mode.state.option.31 = Pulse channel-type.wiz.light-mode.state.option.32 = Steampunk + +# channel types + channel-type.wiz.speed.label = Dynamic Light Mode Speed channel-type.wiz.speed.description = Speed of color/intensity changes in dynamic light modes diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 5599997747fcc..9bbbf00f9e14e 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -13,7 +13,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -45,7 +45,7 @@ - + @@ -72,6 +72,9 @@ + + + @@ -133,7 +136,7 @@ - + Dimmer Speed of color/intensity changes in dynamic light modes @@ -142,6 +145,34 @@ + + Number + + + + + + Switch + + + + + + + + + + + Switch + + + + + + + + + DateTime @@ -163,7 +194,7 @@ - + @@ -171,6 +202,9 @@ + + + From cd747634a1e9b333232dbcfc6338b71199c74095 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 4 Nov 2024 10:23:37 -0700 Subject: [PATCH 11/26] remove "bulb" reference from many places replace it with "device" where relevant, or just remove it completely as a prefix to the config options macAddress and ipAddress Signed-off-by: Cody Cutrer --- .../wiz/internal/WizBindingConstants.java | 6 +- .../config/WizDeviceConfiguration.java | 4 +- .../discovery/WizDiscoveryService.java | 90 ++++++------ .../wiz/internal/handler/WizHandler.java | 131 +++++++++--------- .../wiz/internal/handler/WizMediatorImpl.java | 6 +- .../main/resources/OH-INF/config/config.xml | 25 ++-- .../main/resources/OH-INF/i18n/wiz.properties | 33 +++-- .../resources/OH-INF/thing/thing-types.xml | 18 +-- 8 files changed, 160 insertions(+), 153 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index 17999c1e859ad..9fb9f3c446523 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -75,13 +75,13 @@ public class WizBindingConstants { /** * Mac address configuration argument key. */ - public static final String CONFIG_MAC_ADDRESS = "bulbMacAddress"; + public static final String CONFIG_MAC_ADDRESS = "macAddress"; public static final String MISSING_INVALID_MAC_ADDRESS = "bulbMacAddress"; /** * Host address configuration argument key. */ - public static final String CONFIG_IP_ADDRESS = "bulbIpAddress"; + public static final String CONFIG_IP_ADDRESS = "ipAddress"; /** * Wifi socket update interval configuration argument key. @@ -106,7 +106,7 @@ public class WizBindingConstants { /** * Default Wifi socket default UDP port. */ - public static final int DEFAULT_BULB_UDP_PORT = 38899; + public static final int DEFAULT_UDP_PORT = 38899; /** * Default listener socket default UDP port. diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java index dcecb97a329b8..5f54d89673a9d 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java @@ -28,8 +28,8 @@ public class WizDeviceConfiguration { /** * Configuration for a WiZ Device */ - public String bulbMacAddress = MISSING_INVALID_MAC_ADDRESS; - public String bulbIpAddress = ""; + public String macAddress = MISSING_INVALID_MAC_ADDRESS; + public String ipAddress = ""; public long updateInterval = DEFAULT_REFRESH_INTERVAL_SEC; public boolean useHeartBeats = false; // true: register to get 5s heart-beats public long reconnectInterval = DEFAULT_RECONNECT_INTERVAL_MIN; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java index 08afefbaf22ae..4bfcf0e1ed822 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java @@ -64,7 +64,7 @@ public class WizDiscoveryService extends AbstractDiscoveryService { private final WizPacketConverter converter = new WizPacketConverter(); - private @Nullable ScheduledFuture bulbBackgroudDiscovery; + private @Nullable ScheduledFuture backgroundDiscovery; /** * Constructor of the discovery service. @@ -90,22 +90,22 @@ public Set getSupportedThingTypes() { * is called with true as parameter and when the component is being activated * (see {@link AbstractDiscoveryService#activate()}. * - * This will also serve to "re-discover" any bulbs that have changed to a new IP address. + * This will also serve to "re-discover" any devices that have changed to a new IP address. */ @Override protected void startBackgroundDiscovery() { - ScheduledFuture backgroundDiscovery = bulbBackgroudDiscovery; + ScheduledFuture backgroundDiscovery = this.backgroundDiscovery; if (backgroundDiscovery == null || backgroundDiscovery.isCancelled()) { - bulbBackgroudDiscovery = scheduler.scheduleWithFixedDelay(this::startScan, 1, 60, TimeUnit.MINUTES); + this.backgroundDiscovery = scheduler.scheduleWithFixedDelay(this::startScan, 1, 60, TimeUnit.MINUTES); } } @Override protected void stopBackgroundDiscovery() { - ScheduledFuture backgroundDiscovery = bulbBackgroudDiscovery; + ScheduledFuture backgroundDiscovery = this.backgroundDiscovery; if (backgroundDiscovery != null && !backgroundDiscovery.isCancelled()) { backgroundDiscovery.cancel(true); - bulbBackgroudDiscovery = null; + this.backgroundDiscovery = null; } } @@ -122,20 +122,20 @@ protected void startScan() { byte[] message = this.converter.transformToByteMessage(request); // Initialize a datagram packet with data and address - DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_BULB_UDP_PORT); + DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_UDP_PORT); // Create a datagram socket, send the packet through it, close it. // For discovery we will "fire and forget" and let the mediator take care of the // responses dsocket = new DatagramSocket(); dsocket.send(packet); - logger.debug("Broadcast packet to address: {} and port {}", address, DEFAULT_BULB_UDP_PORT); + logger.debug("Broadcast packet to address: {} and port {}", address, DEFAULT_UDP_PORT); } else { logger.warn("No broadcast address was configured or discovered! No broadcast sent."); } } catch (IOException exception) { logger.debug("Something wrong happened when broadcasting the packet to port {}... msg: {}", - DEFAULT_BULB_UDP_PORT, exception.getMessage()); + DEFAULT_UDP_PORT, exception.getMessage()); } finally { if (dsocket != null) { dsocket.close(); @@ -144,17 +144,17 @@ protected void startScan() { } /** - * Method called by mediator, after receiving a packet from an unknown WiZ bulb + * Method called by mediator, after receiving a packet from an unknown WiZ device * - * @param bulbMacAddress the mac address from the device. - * @param bulbIpAddress the host address from the device. + * @param macAddress the mac address from the device. + * @param ipAddress the host address from the device. */ - public void discoveredLight(final String lightMacAddress, final String lightIpAddress) { + public void discoveredLight(final String macAddress, final String ipAddress) { Map properties = new HashMap<>(2); - properties.put(CONFIG_MAC_ADDRESS, lightMacAddress); - properties.put(CONFIG_IP_ADDRESS, lightIpAddress); - logger.trace("New bulb discovered at {} with MAC {}. Requesting configuration info from the bulb.", - lightIpAddress, lightMacAddress); + properties.put(CONFIG_MAC_ADDRESS, macAddress); + properties.put(CONFIG_IP_ADDRESS, ipAddress); + logger.trace("New device discovered at {} with MAC {}. Requesting configuration info from it.", ipAddress, + macAddress); // Assume it is a full color bulb, unless we get confirmation otherwise. // This will ensure the maximum number of channels will be created so there's no @@ -165,62 +165,62 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd // The bulbs will merely ignore or return an error for specific commands they // cannot carry-out (ie, setting color on a non-color bulb) and continue to // function as they were before the bad command. - ThingTypeUID thisBulbType = THING_TYPE_COLOR_BULB; - String thisBulbLabel = "WiZ Full Color Bulb at " + lightIpAddress; - ThingUID newThingId = new ThingUID(thisBulbType, lightMacAddress); + ThingTypeUID thisDeviceType = THING_TYPE_COLOR_BULB; + String thisDeviceLabel = "WiZ Full Color Bulb at " + ipAddress; + ThingUID newThingId = new ThingUID(thisDeviceType, macAddress); - WizResponse configResponse = getDiscoveredBulbConfig(lightIpAddress); + WizResponse configResponse = getDiscoveredDeviceConfig(ipAddress); if (configResponse != null) { - SystemConfigResult discoveredBulbConfig = configResponse.getSystemConfigResults(); - if (discoveredBulbConfig != null) { - String discoveredModel = discoveredBulbConfig.moduleName.toUpperCase(); - logger.trace("Returned model from discovered bulb at {}: {}", lightIpAddress, discoveredModel); + SystemConfigResult discoveredDeviceConfig = configResponse.getSystemConfigResults(); + if (discoveredDeviceConfig != null) { + String discoveredModel = discoveredDeviceConfig.moduleName.toUpperCase(); + logger.trace("Returned model from discovered device at {}: {}", ipAddress, discoveredModel); // “moduleName”:“ESP10_SOCKET_06” confirmed example module name for Wiz Smart Plug // Check for "SOCKET" this seems safe based on other naming conventions observed if (discoveredModel.contains("SOCKET")) { - thisBulbType = THING_TYPE_SMART_PLUG; - thisBulbLabel = "WiZ Smart Plug at " + lightIpAddress; - newThingId = new ThingUID(thisBulbType, lightMacAddress); + thisDeviceType = THING_TYPE_SMART_PLUG; + thisDeviceLabel = "WiZ Smart Plug at " + ipAddress; + newThingId = new ThingUID(thisDeviceType, macAddress); logger.trace("New device appears to be a smart plug and will be given the UUID: {}", newThingId); // We'll try to key off "TW" for tunable white } else if (discoveredModel.contains("TW")) { - thisBulbType = THING_TYPE_TUNABLE_BULB; - thisBulbLabel = "WiZ Tunable White Bulb at " + lightIpAddress; - newThingId = new ThingUID(thisBulbType, lightMacAddress); - logger.trace("New bulb appears to be a tunable white bulb and will be given the UUID: {}", + thisDeviceType = THING_TYPE_TUNABLE_BULB; + thisDeviceLabel = "WiZ Tunable White Bulb at " + ipAddress; + newThingId = new ThingUID(thisDeviceType, macAddress); + logger.trace("New device appears to be a tunable white bulb and will be given the UUID: {}", newThingId); // Check for "FANDIMS" as in confirmed example ESP03_FANDIMS_31 for Faro Barcelona Smart Fan } else if (discoveredModel.contains("FANDIMS")) { - thisBulbType = THING_TYPE_FAN; - thisBulbLabel = "WiZ Smart Fan at " + lightIpAddress; - newThingId = new ThingUID(thisBulbType, lightMacAddress); + thisDeviceType = THING_TYPE_FAN; + thisDeviceLabel = "WiZ Smart Fan at " + ipAddress; + newThingId = new ThingUID(thisDeviceType, macAddress); logger.trace("New device appears to be a smart fan and will be given the UUID: {}", newThingId); // We key off "RGB" for color bulbs } else if (!discoveredModel.contains("RGB")) { - thisBulbType = THING_TYPE_DIMMABLE_BULB; - thisBulbLabel = "WiZ Dimmable White Bulb at " + lightIpAddress; - newThingId = new ThingUID(thisBulbType, lightMacAddress); + thisDeviceType = THING_TYPE_DIMMABLE_BULB; + thisDeviceLabel = "WiZ Dimmable White Bulb at " + ipAddress; + newThingId = new ThingUID(thisDeviceType, macAddress); logger.trace( - "New bulb appears not to be either tunable white bulb or full color and will be called dimmable only and given the UUID: {}", + "New device appears not to be either tunable white bulb or full color and will be called a dimmable only bulb and given the UUID: {}", newThingId); } DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(newThingId).withProperties(properties) - .withLabel(thisBulbLabel).withRepresentationProperty(CONFIG_MAC_ADDRESS).build(); + .withLabel(thisDeviceLabel).withRepresentationProperty(CONFIG_MAC_ADDRESS).build(); this.thingDiscovered(discoveryResult); } } else { logger.trace( - "Couldn't get or couldn't parse configuration information from discovered bulb. Discovery result will not be created."); + "Couldn't get or couldn't parse configuration information from discovered device. Discovery result will not be created."); } } - private synchronized @Nullable WizResponse getDiscoveredBulbConfig(final String lightIpAddress) { + private synchronized @Nullable WizResponse getDiscoveredDeviceConfig(final String lightIpAddress) { DatagramSocket dsocket = null; try { WizRequest request = new WizRequest(WizMethodType.GetSystemConfig, null); @@ -230,12 +230,12 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd // Initialize a datagram packet with data and address InetAddress address = InetAddress.getByName(lightIpAddress); - DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_BULB_UDP_PORT); + DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_UDP_PORT); // Create a datagram socket, send the packet through it, close it. dsocket = new DatagramSocket(); dsocket.send(packet); - logger.debug("Sent packet to address: {} and port {}", address, DEFAULT_BULB_UDP_PORT); + logger.debug("Sent packet to address: {} and port {}", address, DEFAULT_UDP_PORT); byte[] responseMessage = new byte[1024]; packet = new DatagramPacket(responseMessage, responseMessage.length); @@ -246,7 +246,7 @@ public void discoveredLight(final String lightMacAddress, final String lightIpAd logger.trace("Socket timeout after sending command; no response from {} within 500ms", lightIpAddress); } catch (IOException exception) { logger.debug("Something wrong happened when sending the packet to address: {} and port {}... msg: {}", - lightIpAddress, DEFAULT_BULB_UDP_PORT, exception.getMessage()); + lightIpAddress, DEFAULT_UDP_PORT, exception.getMessage()); } finally { if (dsocket != null) { dsocket.close(); diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 0da0e59a2f999..3a5d4158ba676 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -138,8 +138,8 @@ public WizHandler(final Thing thing, final RegistrationRequestParam registration public void handleCommand(final ChannelUID channelUID, final Command command) { if (hasConfigurationError() || disposed || !fullyInitialized) { logger.debug( - "[{}] WiZ handler for blub {} received command {} on channel {} but is not yet prepared to handle it.", - config.bulbIpAddress, config.bulbMacAddress, command, channelUID); + "[{}] WiZ handler for device {} received command {} on channel {} but is not yet prepared to handle it.", + config.ipAddress, config.macAddress, command, channelUID); return; } @@ -281,13 +281,13 @@ private void handleLightModeCommand(Command command) { mostRecentState.sceneId = commandAsLightMode.getSceneId(); setPilotCommand(new SceneRequestParam(commandAsLightMode.getSceneId())); } else { - logger.warn("[{}] Command [{}] not a recognized Light Mode!", config.bulbIpAddress, command); + logger.warn("[{}] Command [{}] not a recognized Light Mode!", config.ipAddress, command); } } private void handleHSBCommand(HSBType hsb) { if (hsb.getBrightness().intValue() == 0) { - logger.debug("[{}] Zero intensity requested, turning bulb off.", config.bulbIpAddress); + logger.debug("[{}] Zero intensity requested, turning bulb off.", config.ipAddress); setPilotCommand(new StateRequestParam(false)); } else { setPilotCommand(new ColorRequestParam(hsb)); @@ -297,7 +297,7 @@ private void handleHSBCommand(HSBType hsb) { private void handlePercentCommand(PercentType brightness) { if (brightness.equals(PercentType.ZERO)) { - logger.debug("[{}] Zero brightness requested, turning bulb off.", config.bulbIpAddress); + logger.debug("[{}] Zero brightness requested, turning bulb off.", config.ipAddress); setPilotCommand(new StateRequestParam(false)); } else { setPilotCommand(new DimmingRequestParam(brightness.intValue())); @@ -338,7 +338,7 @@ private void handleIncreaseDecreaseCommand(boolean isIncrease) { } else { newDimming = Math.max(10, oldDimming - 5); } - logger.debug("[{}] Changing bulb brightness from {}% to {}%.", config.bulbIpAddress, oldDimming, newDimming); + logger.debug("[{}] Changing bulb brightness from {}% to {}%.", config.ipAddress, oldDimming, newDimming); handlePercentCommand(new PercentType(newDimming)); } @@ -355,7 +355,7 @@ private void handleIncreaseDecreaseTemperatureCommand(boolean isIncrease) { } else { newTempPct = Math.max(0, oldTempPct - 5); } - logger.debug("[{}] Changing color temperature from {}% to {}%.", config.bulbIpAddress, oldTempPct, newTempPct); + logger.debug("[{}] Changing color temperature from {}% to {}%.", config.ipAddress, oldTempPct, newTempPct); handleTemperatureCommand(percentToColorTemp(new PercentType(BigDecimal.valueOf(newTempPct)))); } @@ -392,18 +392,18 @@ private synchronized void initGetStatusAndKeepAliveThread() { long timePassedFromLastUpdateInSeconds = (now - latestUpdate) / 1000; long timePassedFromLastRefreshInSeconds = (now - latestOfflineRefresh) / 1000; - // If the bulb has an online status, check if we it's been too long since the + // If the device has an online status, check if we it's been too long since the // last response and re-set offline accordingly if (getThing().getStatus() == ThingStatus.ONLINE) { - logger.trace("[{}] MAC address: {} Latest Update: {} Now: {} Delta: {} seconds", config.bulbIpAddress, - config.bulbMacAddress, latestUpdate, now, timePassedFromLastUpdateInSeconds); + logger.trace("[{}] MAC address: {} Latest Update: {} Now: {} Delta: {} seconds", config.ipAddress, + config.macAddress, latestUpdate, now, timePassedFromLastUpdateInSeconds); boolean considerThingOffline = (latestUpdate < 0) || (timePassedFromLastUpdateInSeconds > MARK_OFFLINE_AFTER_SEC); if (considerThingOffline) { logger.debug( "[{}] Since no updates have been received from mac address {} in {} seconds, setting its status to OFFLINE and discontinuing polling.", - config.bulbIpAddress, config.bulbMacAddress, MARK_OFFLINE_AFTER_SEC); + config.ipAddress, config.macAddress, MARK_OFFLINE_AFTER_SEC); updateStatus(ThingStatus.OFFLINE); } @@ -414,20 +414,19 @@ private synchronized void initGetStatusAndKeepAliveThread() { if (config.useHeartBeats) { // If we're using 5s heart-beats, we must re-register every 30s to maintain // connection - logger.debug("[{}] Re-registering for heart-beats.", config.bulbIpAddress); - registerWithBulb(); + logger.debug("[{}] Re-registering for heart-beats.", config.ipAddress); + registerWithDevice(); } else { // If we're not using heart-beats, just request the current status - logger.debug("[{}] Polling for status from bulb at {}.", config.bulbIpAddress, - config.bulbMacAddress); + logger.debug("[{}] Polling for status from device at {}.", config.ipAddress, config.macAddress); getPilot(); } - // Else if we are offline, but it's been a while, re-check if the bulb re-appeared + // Else if we are offline, but it's been a while, re-check if the device re-appeared } else if (timePassedFromLastRefreshInSeconds > config.reconnectInterval * 60) { // Request the current status - logger.debug("[{}] Checking for reappearance of offline bulb at {}.", config.bulbIpAddress, - config.bulbMacAddress); + logger.debug("[{}] Checking for reappearance of offline device at {}.", config.ipAddress, + config.macAddress); latestOfflineRefresh = now; getPilot(); } @@ -436,12 +435,12 @@ private synchronized void initGetStatusAndKeepAliveThread() { * Schedule the keep-alive job. * * The scheduling inteval is: - * - every 30 seconds for online bulbs receiving heart-beats - * - every config.updateInterval for other online bulbs + * - every 30 seconds for online devices receiving heart-beats + * - every config.updateInterval for other online devices */ long updateIntervalInUse = config.useHeartBeats ? 30 : config.updateInterval; - logger.debug("[{}] Scheduling reoccuring keep alive for every {} seconds for bulb at {}.", config.bulbIpAddress, - updateIntervalInUse, config.bulbMacAddress); + logger.debug("[{}] Scheduling reoccuring keep alive for every {} seconds for device at {}.", config.ipAddress, + updateIntervalInUse, config.macAddress); this.keepAliveJob = scheduler.scheduleWithFixedDelay(runnable, 1, updateIntervalInUse, TimeUnit.SECONDS); } @@ -453,10 +452,10 @@ public void initialize() { // set the thing status to UNKNOWN temporarily updateStatus(ThingStatus.UNKNOWN); - if (ValidationUtils.isMacNotValid(config.bulbMacAddress)) { + if (ValidationUtils.isMacNotValid(config.macAddress)) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "MAC address is not valid"); } - updateBulbProperties(); + updateDeviceProperties(); initGetStatusAndKeepAliveThread(); fullyInitialized = true; } @@ -483,35 +482,35 @@ private synchronized void getPilot() { updateTimestamps(); updateStatesFromParams(rParam); } else { - logger.trace("[{}] No parameters in getPilot response!", config.bulbIpAddress); + logger.trace("[{}] No parameters in getPilot response!", config.ipAddress); } } else { - logger.trace("[{}] No response from getPilot request!", config.bulbIpAddress); + logger.trace("[{}] No response from getPilot request!", config.ipAddress); } } /** * Method called by {@link WizMediator} when any "unsolicited" messages - * come in on the listening socket and appear to be a WiZ bulb. "Unsolicited" - * messages from the bulb are could be: - * - a "firstBeat" broadcast to the subnet by the bulb on first powering up - * - an "hb" (heartbeat) specifically directed to OpenHab within 30 seconds of registration - * - or a response to a registration request broadcast by this binding to all bulbs on the subnet + * come in on the listening socket and appear to be a WiZ device. "Unsolicited" + * messages from the device could be: + * - a "firstBeat" broadcast to the subnet by the device on first powering up + * - an "hb" (heartbeat) specifically directed to openHAB within 30 seconds of registration + * - or a response to a registration request broadcast by this binding to all devices on the subnet * - * @note The mediator finds the correct handler for the bulb based on the (unchanging) bulb + * @note The mediator finds the correct handler for the device based on the (unchanging) device * MAC address. If the mediator matches a message to the handler by MAC address, but the IP address - * the message came from doesn't match the bulb's configured IP address, this will update the - * bulb's configuration to reflect whatever the current IP is. + * the message came from doesn't match the device's configured IP address, this will update the + * device's configuration to reflect whatever the current IP is. * * @param receivedMessage the received {@link WizResponse}. */ public synchronized void newReceivedResponseMessage(final WizResponse receivedMessage) { Boolean updatePropertiesAfterParams = false; - // Check if the bulb still has the same IP address it had previously + // Check if the device still has the same IP address it had previously // If not, we need to update the configuration for the thing. if (!receivedMessage.getWizResponseIpAddress().isEmpty() - && !receivedMessage.getWizResponseIpAddress().equals(this.getBulbIpAddress())) { + && !receivedMessage.getWizResponseIpAddress().equals(this.getIpAddress())) { // get the old config Configuration priorConfig = getConfig(); // change the ip address property @@ -524,7 +523,7 @@ public synchronized void newReceivedResponseMessage(final WizResponse receivedMe updatePropertiesAfterParams = true; } - // Grab the ID number and mark the bulb online + // Grab the ID number and mark the device online requestId = receivedMessage.getId(); updateTimestamps(); @@ -534,10 +533,10 @@ public synchronized void newReceivedResponseMessage(final WizResponse receivedMe updateStatesFromParams(params); } - // After updating state, we'll update all other bulb parameters from bulbs that + // After updating state, we'll update all other device parameters from devices that // presented with a new IP address. if (updatePropertiesAfterParams) { - updateBulbProperties(); + updateDeviceProperties(); } } @@ -598,7 +597,7 @@ private void updateLightStatesFromParams(final WizSyncState receivedParam) { case RGBMode: logger.trace( "[{}] Received color values - R: {} G: {} B: {} W: {} C: {} Dimming: {}; translate to HSBType: {}", - config.bulbIpAddress, receivedParam.r, receivedParam.g, receivedParam.b, receivedParam.w, + config.ipAddress, receivedParam.r, receivedParam.g, receivedParam.b, receivedParam.w, receivedParam.c, receivedParam.dimming, receivedParam.getHSBColor()); updateLightState(CHANNEL_COLOR, receivedParam.getHSBColor()); @@ -649,7 +648,7 @@ private void updateFanStatesFromParams(final WizSyncState receivedParam) { final @Nullable Param param) { DatagramSocket dsocket = null; try { - InetAddress address = InetAddress.getByName(config.bulbIpAddress); + InetAddress address = InetAddress.getByName(config.ipAddress); if (address != null) { WizRequest request = new WizRequest(method, param); request.setId(requestId++); @@ -658,7 +657,7 @@ private void updateFanStatesFromParams(final WizSyncState receivedParam) { logger.trace("Raw packet to send: {}", message); // Initialize a datagram packet with data and address - DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_BULB_UDP_PORT); + DatagramPacket packet = new DatagramPacket(message, message.length, address, DEFAULT_UDP_PORT); // Create a datagram socket, send the packet through it, close it. dsocket = new DatagramSocket(null); @@ -666,8 +665,8 @@ private void updateFanStatesFromParams(final WizSyncState receivedParam) { dsocket.setBroadcast(true); dsocket.setSoTimeout(500); // Timeout in 500ms dsocket.send(packet); - logger.debug("[{}] Sent packet to address: {} and port {}", config.bulbIpAddress, address, - DEFAULT_BULB_UDP_PORT); + logger.debug("[{}] Sent packet to address: {} and port {}", config.ipAddress, address, + DEFAULT_UDP_PORT); byte[] responseMessage = new byte[1024]; packet = new DatagramPacket(responseMessage, responseMessage.length); @@ -677,10 +676,10 @@ private void updateFanStatesFromParams(final WizSyncState receivedParam) { } } catch (SocketTimeoutException e) { logger.trace("[{}] Socket timeout after sending command; no response from {} within 500ms", - config.bulbIpAddress, config.bulbMacAddress); + config.ipAddress, config.macAddress); } catch (IOException exception) { logger.debug("[{}] Something wrong happened when sending the packet to port {}... msg: {}", - config.bulbIpAddress, DEFAULT_BULB_UDP_PORT, exception.getMessage()); + config.ipAddress, DEFAULT_UDP_PORT, exception.getMessage()); } finally { if (dsocket != null) { dsocket.close(); @@ -712,7 +711,7 @@ private synchronized boolean setPilotCommand(final @Nullable Param param) { } /** - * Makes note of the latest timestamps and sets the bulb online + * Makes note of the latest timestamps and sets the device online */ private synchronized void updateTimestamps() { if (hasConfigurationError() || disposed) { @@ -726,9 +725,9 @@ private synchronized void updateTimestamps() { } /** - * Asks the bulb for its current system configuration + * Asks the device for its current system configuration */ - private synchronized void updateBulbProperties() { + private synchronized void updateDeviceProperties() { if (hasConfigurationError() || disposed) { return; } @@ -753,8 +752,8 @@ private synchronized void updateBulbProperties() { updateTimestamps(); } else { logger.debug( - "[{}] Received response to getConfigRequest from bulb at {}, but id did not contain bulb configuration information.", - config.bulbIpAddress, config.bulbMacAddress); + "[{}] Received response to getConfigRequest from device at {}, but it did not contain device configuration information.", + config.ipAddress, config.macAddress); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); } @@ -773,37 +772,37 @@ private synchronized void updateBulbProperties() { Objects.requireNonNull(stateDescription)); } } else { - // Not a big deal; probably just an older bulb - logger.warn("[{}] No response to getModelConfig request from bulb", config.bulbIpAddress); + // Not a big deal; probably just an older device + logger.warn("[{}] No response to getModelConfig request from device", config.ipAddress); } } else { - logger.debug("[{}] No response to getSystemConfig request from bulb at {}", config.bulbIpAddress, - config.bulbMacAddress); + logger.debug("[{}] No response to getSystemConfig request from device at {}", config.ipAddress, + config.macAddress); // Not calling it "gone" because it's probably just been powered off and will beback any time updateStatus(ThingStatus.OFFLINE); } } /** - * Registers with the bulb - this tells the bulb to begin sending 5-second - * heartbeat (hb) status updates. Status updates are sent by the bulb every 5 + * Registers with the device - this tells the device to begin sending 5-second + * heartbeat (hb) status updates. Status updates are sent by the device every 5 * sec and on any state change for 30s after registration. For continuous * heart-beats the registration must be re-sent after 30s. */ - private synchronized void registerWithBulb() { + private synchronized void registerWithDevice() { WizResponse registrationResponse = sendRequestPacket(WizMethodType.Registration, this.registrationInfo); if (registrationResponse != null) { if (registrationResponse.getResultSuccess()) { updateTimestamps(); } else { logger.debug( - "[{}] Received response to getConfigRequest from bulb at {}, but id did not contain bulb configuration information.", - config.bulbIpAddress, config.bulbMacAddress); + "[{}] Received response to getConfigRequest from device at {}, but it did not contain device configuration information.", + config.ipAddress, config.macAddress); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); } } else { - logger.debug("[{}] No response to registration request from bulb at {}", config.bulbIpAddress, - config.bulbMacAddress); + logger.debug("[{}] No response to registration request from device at {}", config.ipAddress, + config.macAddress); // Not calling it "gone" because it's probably just been powered off and will be // back any time updateStatus(ThingStatus.OFFLINE); @@ -827,12 +826,12 @@ private PercentType colorTempToPercent(int temp) { } // SETTERS AND GETTERS - public String getBulbIpAddress() { - return config.bulbIpAddress; + public String getIpAddress() { + return config.ipAddress; } - public String getBulbMacAddress() { - return config.bulbMacAddress; + public String getMacAddress() { + return config.macAddress; } public int getHomeId() { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java index 567273424e923..799de0f95412c 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java @@ -146,13 +146,13 @@ public void unregisterWizBulbHandlerByThing(final Thing thing) { * Utility method to get the registered thing handler in mediator by the mac * address. * - * @param bulbMacAddress the mac address of the thing of the handler. + * @param macAddress the mac address of the thing of the handler. * @return {@link WizHandler} if found. */ - private @Nullable WizHandler getHandlerRegisteredByMac(final String bulbMacAddress) { + private @Nullable WizHandler getHandlerRegisteredByMac(final String macAddress) { WizHandler searchedHandler = null; for (WizHandler handler : this.handlersRegisteredByThing.values()) { - if (bulbMacAddress.equalsIgnoreCase(handler.getBulbMacAddress())) { + if (macAddress.equalsIgnoreCase(handler.getMacAddress())) { searchedHandler = handler; // don't spend more computation. Found the handler. break; diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/config/config.xml index 4873139d8d68b..bcea53ad47031 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/config/config.xml @@ -4,35 +4,36 @@ xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd"> - - - - MAC address of the bulb + + + + MAC address of the device true - - + + network-address - IP address of the bulb + IP address of the device true - Update time interval in seconds to request the status of the bulb while it is connected to the network. + Update time interval in seconds to request the status of the device while it is connected to the + network. 60 true - True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. + True to request continuous 5s heartbeats from device. Update interval is ignored when using heartbeats. true false - Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status - queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to - immediately detect it. This is only as a back-up to re-find the bulb. + Interval in minutes between attempts to reconnect with a device that is no longer responding to status + queries. When the device first connects to the network, it should send out a firstBeat message allowing openHAB to + immediately detect it. This is only as a back-up to re-find the device. 15 true diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties index a86cb4546af04..95c3deeaca950 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties @@ -20,16 +20,16 @@ thing-type.wiz.tunable-bulb.description = Supports WiZ Tunable White Bulbs # thing types config -thing-type.config.wiz.light.bulbIpAddress.label = Bulb IP Address -thing-type.config.wiz.light.bulbIpAddress.description = IP address of the bulb -thing-type.config.wiz.light.bulbMacAddress.label = Bulb MAC Address -thing-type.config.wiz.light.bulbMacAddress.description = MAC address of the bulb -thing-type.config.wiz.light.reconnectInterval.label = Reconnect Interval -thing-type.config.wiz.light.reconnectInterval.description = Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. -thing-type.config.wiz.light.updateInterval.label = Update Interval -thing-type.config.wiz.light.updateInterval.description = Update time interval in seconds to request the status of the bulb while it is connected to the network. -thing-type.config.wiz.light.useHeartBeats.label = Use Heartbeats -thing-type.config.wiz.light.useHeartBeats.description = True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. +thing-type.config.wiz.device.ipAddress.label = IP Address +thing-type.config.wiz.device.ipAddress.description = IP address of the device +thing-type.config.wiz.device.macAddress.label = MAC Address +thing-type.config.wiz.device.macAddress.description = MAC address of the device +thing-type.config.wiz.device.reconnectInterval.label = Reconnect Interval +thing-type.config.wiz.device.reconnectInterval.description = Interval in minutes between attempts to reconnect with a device that is no longer responding to status queries. When the device first connects to the network, it should send out a firstBeat message allowing openHAB to immediately detect it. This is only as a back-up to re-find the device. +thing-type.config.wiz.device.updateInterval.label = Update Interval +thing-type.config.wiz.device.updateInterval.description = Update time interval in seconds to request the status of the device while it is connected to the network. +thing-type.config.wiz.device.useHeartBeats.label = Use Heartbeats +thing-type.config.wiz.device.useHeartBeats.description = True to request continuous 5s heartbeats from device. Update interval is ignored when using heartbeats. # channel group types @@ -84,6 +84,19 @@ channel-type.wiz.light-mode.state.option.30 = Golden White channel-type.wiz.light-mode.state.option.31 = Pulse channel-type.wiz.light-mode.state.option.32 = Steampunk +# thing types config + +thing-type.config.wiz.light.ipAddress.label = Bulb IP Address +thing-type.config.wiz.light.ipAddress.description = IP address of the bulb +thing-type.config.wiz.light.bulbMacAddress.label = Bulb MAC Address +thing-type.config.wiz.light.bulbMacAddress.description = MAC address of the bulb +thing-type.config.wiz.light.reconnectInterval.label = Reconnect Interval +thing-type.config.wiz.light.reconnectInterval.description = Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. +thing-type.config.wiz.light.updateInterval.label = Update Interval +thing-type.config.wiz.light.updateInterval.description = Update time interval in seconds to request the status of the bulb while it is connected to the network. +thing-type.config.wiz.light.useHeartBeats.label = Use Heartbeats +thing-type.config.wiz.light.useHeartBeats.description = True to request continuous 5s heartbeats from bulb. Update interval is ignored when using heartbeats. + # channel types channel-type.wiz.speed.label = Dynamic Light Mode Speed diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 9bbbf00f9e14e..3bdd66a4f3a5a 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -3,7 +3,6 @@ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - Supports WiZ Full Color with Tunable White Bulbs @@ -17,10 +16,9 @@ - + - Supports WiZ Tunable White Bulbs @@ -34,10 +32,9 @@ - + - Supports WiZ Single Color Dimmable Bulbs @@ -49,10 +46,9 @@ - + - Supports WiZ Smart Plugs @@ -62,10 +58,9 @@ - + - Supports WiZ Ceiling Fans @@ -76,7 +71,7 @@ - + @@ -88,10 +83,9 @@ - + - String From 53d2a0bb516e1e96289fea82ba904b747e09c3ab Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 4 Nov 2024 10:35:47 -0700 Subject: [PATCH 12/26] fix color temp math and remove extraneous debugging logging Signed-off-by: Cody Cutrer --- .../org/openhab/binding/wiz/internal/handler/WizHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 3a5d4158ba676..d7c9e3c266af1 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -764,7 +764,6 @@ private synchronized void updateDeviceProperties() { if (modelConfigResult != null && modelConfigResult.cctRange.length > 0) { minColorTemp = Arrays.stream(modelConfigResult.cctRange).min().getAsInt(); maxColorTemp = Arrays.stream(modelConfigResult.cctRange).max().getAsInt(); - logger.warn("min temp: {} max temp: {}", minColorTemp, maxColorTemp); StateDescription stateDescription = StateDescriptionFragmentBuilder.create() .withMinimum(BigDecimal.valueOf(minColorTemp)).withMaximum(BigDecimal.valueOf(maxColorTemp)) .withPattern("%.0f K").build().toStateDescription(); @@ -822,7 +821,7 @@ private int percentToColorTemp(PercentType command) { } private PercentType colorTempToPercent(int temp) { - return new PercentType(BigDecimal.valueOf((float) temp - minColorTemp / (maxColorTemp - minColorTemp) * 100)); + return new PercentType(BigDecimal.valueOf(((float) temp - minColorTemp) / (maxColorTemp - minColorTemp) * 100)); } // SETTERS AND GETTERS From 7192b5120db3d4fae8f8908f67d51fa6ec78b99e Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 4 Nov 2024 10:48:07 -0700 Subject: [PATCH 13/26] fans have a _dimmable_ light Signed-off-by: Cody Cutrer --- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 3bdd66a4f3a5a..b6284ad3d5d5c 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -186,7 +186,7 @@ - + From 06e70497223c6124d70dbec6e9f62b83e877bd54 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Sat, 9 Nov 2024 16:50:28 -0700 Subject: [PATCH 14/26] address reviewer comments Signed-off-by: Cody Cutrer --- bundles/org.openhab.binding.wiz/README.md | 35 ++++++++++--------- .../wiz/internal/WizBindingConstants.java | 9 ++--- .../config/WizDeviceConfiguration.java | 2 +- .../discovery/WizDiscoveryService.java | 2 +- .../entities/FirstBeatResponseParam.java | 2 +- .../internal/entities/SystemConfigResult.java | 2 +- .../wiz/internal/entities/WizResponse.java | 2 +- .../wiz/internal/entities/WizSyncState.java | 2 +- .../wiz/internal/handler/WizMediatorImpl.java | 6 ++-- .../runnable/WizUpdateReceiverRunnable.java | 2 +- .../wiz/internal/utils/WizColorConverter.java | 4 +-- .../utils/WizResponseDeserializer.java | 10 +++--- .../resources/OH-INF/thing/thing-types.xml | 1 + 13 files changed, 38 insertions(+), 41 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/README.md b/bundles/org.openhab.binding.wiz/README.md index 81cd3bb11278a..a12e2f56a4f2c 100644 --- a/bundles/org.openhab.binding.wiz/README.md +++ b/bundles/org.openhab.binding.wiz/README.md @@ -10,7 +10,7 @@ They are sold under the Philips brand name. This binding operates completely within the local network - the discovery, control, and status monitoring is entirely over UDP in the local network. The binding never attempts to contact the WiZ servers in any way but does not stop them from doing so independently. -It should not interfere in any way with control of the bulbs via the WiZ app or any other service integrated with the WiZ app (ie: Alexa, IFTTT, SmartThings). +It should not interfere in any way with control of the bulbs via the WiZ app or any other service integrated with the WiZ app (e.g. Alexa, IFTTT, SmartThings). Any changes made to the bulb state outside of openHAB should be detected by the binding and vice-versa. Before using the binding, the bulbs must be set up using the WiZ iOS or Android app. Local control must also be enabled with-in the WiZ app in the app settings. @@ -18,19 +18,22 @@ Local control must also be enabled with-in the WiZ app in the app settings. ## Supported Things -* WiZ Full Color with Tunable White Bulbs -* WiZ Tunable White Bulbs -* WiZ Dimmable single-color bulbs -* Wiz Smart Plugs +- WiZ Full Color with Tunable White Bulbs +- WiZ Tunable White Bulbs +- WiZ Dimmable single-color bulbs +- WiZ Smart Plugs +- Smart fans (with or without a dimmable light) _Note_ This binding was created for and tested on the full color with tunable white bulbs, however, users have reported success with other bulb types and plugs. ## Discovery New devices can be discovered by scanning and may also be discovered by background discovery. -All discovered devices will default to 'Full Color' bulbs if unable to automatically detect the specific device type. You may need to create devices manually if desired. +All discovered devices will default to 'Full Color' bulbs if unable to automatically detect the specific device type. +You may need to create devices manually if desired. -Devices must first have been set up using the WiZ iOS or Android app. If the binding cannot discover your device, try unplugging it, wait several seconds, and plug it back in. +Devices must first have been set up using the WiZ iOS or Android app. +If the binding cannot discover your device, try unplugging it, wait several seconds, and plug it back in. ## Binding Configuration @@ -40,13 +43,13 @@ You can optionally manually set the IP and MAC address of the openHAB instance; ## Thing Configuration To create or configure a device manually you need its IP address and MAC address. -These can be quickly found in the ios or android app by entering the settings for device in question and clicking on the model name. +These can be quickly found in the iOS or Android app by entering the settings for device in question and clicking on the model name. The refresh interval may also be set; if unset it defaults to 30 seconds. If you desire instant updates, you may also enable "heart-beat" synchronization with the bulbs. Heart-beats are not used by default. When heart-beats are enabled, the binding will continuously re-register with the bulbs to receive sync packets on every state change and on every 5 seconds. Enabling heart-beats causes the refresh-interval to be ignored. -If heart-beats are not enabled, the channels are only updated when polled at the set interval and thus will be slightly delayed wrt changes made to the bulb state outside of the binding (ie, via the WiZ app). +If heart-beats are not enabled, the channels are only updated when polled at the set interval and thus will be slightly delayed with regard to changes made to the bulb state outside of the binding (e.g. via the WiZ app). **NOTE:** While the bulb's IP address is needed for initial manual configuration, this binding _does not_ require you to use a static IP for each bulb. After initial discovery or setup, the binding will automatically search for and re-match bulbs with changed IP addresses by MAC address once every hour. @@ -59,19 +62,19 @@ Thing parameters: | ipAddress | text | true | The IP of the bulb | | | updateInterval | integer | false | Update time interval in seconds to request the status of the bulb. | 60 | | useHeartBeats | boolean | false | Whether to register for continuous 5s heart-beats | false | -| reconnectInterval | integer | false | Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing OpenHab to immediately detect it. This is only as a back-up to re-find the bulb. | 15 | +| reconnectInterval | integer | false | Interval in minutes between attempts to reconnect with a bulb that is no longer responding to status queries. When the bulb first connects to the network, it should send out a firstBeat message allowing openHAB to immediately detect it. This is only as a back-up to re-find the bulb. | 15 | Example Thing: -``` +```java Thing wiz:bulb:lamp "My Lamp" @ "Living Room" [ macAddress="accf23343cxx", ipAddress="192.168.0.xx" ] ``` ## Channels -The Binding supports the following channels: +The binding supports the following channels: -| Channel Type ID | Item Type | Description | Access | +| Channel ID | Item Type | Description | Access | |-----------------|--------------------|-------------------------------------------------------|--------| | color | Color | State, intensity, and color of the LEDs | R/W | | temperature | Dimmer | Color temperature of the bulb | R/W | @@ -80,12 +83,12 @@ The Binding supports the following channels: | state | Switch | Whether the bulb is on or off | R/W | | light-mode | Number | Preset light mode name to run | R/W | | speed | Dimmer | Speed of the color changes in dynamic light modes | R/W | -| signal-strength | system | Quality of the bulb's WiFi connection | R | +| signal-strength | Number | Quality of the bulb's WiFi connection | R | | last-update | Time | The last time an an update was received from the bulb | R | ## Light Modes -The Binding supports the following Light Modes +The binding supports the following Light Modes | ID | Scene Name | |----|---------------| @@ -136,6 +139,6 @@ Sending a command on the color channel or the temperature channel will cause the ## Example item linked to a channel -``` +```java Color LivingRoom_Light_Color "Living Room Lamp" (gLivingroom) {channel="wiz:color-bulb:accf23343cxx:color"} ``` diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index 9fb9f3c446523..825f528d05d1b 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -13,8 +13,6 @@ package org.openhab.binding.wiz.internal; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.core.thing.ThingTypeUID; @@ -48,10 +46,8 @@ public class WizBindingConstants { /** * The supported thing types. */ - public static final Set SUPPORTED_THING_TYPES = Stream - .of(THING_TYPE_COLOR_BULB, THING_TYPE_TUNABLE_BULB, THING_TYPE_DIMMABLE_BULB, THING_TYPE_SMART_PLUG, - THING_TYPE_FAN, THING_TYPE_FAN_WITH_DIMMABLE_BULB) - .collect(Collectors.toSet()); + public static final Set SUPPORTED_THING_TYPES = Set.of(THING_TYPE_COLOR_BULB, THING_TYPE_TUNABLE_BULB, + THING_TYPE_DIMMABLE_BULB, THING_TYPE_SMART_PLUG, THING_TYPE_FAN, THING_TYPE_FAN_WITH_DIMMABLE_BULB); /** * List of all Channel ids @@ -76,7 +72,6 @@ public class WizBindingConstants { * Mac address configuration argument key. */ public static final String CONFIG_MAC_ADDRESS = "macAddress"; - public static final String MISSING_INVALID_MAC_ADDRESS = "bulbMacAddress"; /** * Host address configuration argument key. diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java index 5f54d89673a9d..abf108fdd42cd 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/config/WizDeviceConfiguration.java @@ -28,7 +28,7 @@ public class WizDeviceConfiguration { /** * Configuration for a WiZ Device */ - public String macAddress = MISSING_INVALID_MAC_ADDRESS; + public String macAddress = ""; public String ipAddress = ""; public long updateInterval = DEFAULT_REFRESH_INTERVAL_SEC; public boolean useHeartBeats = false; // true: register to get 5s heart-beats diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java index 4bfcf0e1ed822..82232d95ac0b5 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java @@ -48,7 +48,7 @@ import org.slf4j.LoggerFactory; /** - * This is the {@link DiscoveryService} for the WiZ Items. + * This is the {@link DiscoveryService} for the WiZ Things. * * @author Sriram Balakrishnan - Initial contribution * @author Joshua Freeman - use configured Broadcast address instead of guessing, discovery of plugs diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java index 949ec1522e0ef..ee01cb2df41d7 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java @@ -32,7 +32,7 @@ public class FirstBeatResponseParam { // The MAC address the response is coming from @Expose(serialize = true, deserialize = true) - public String mac = MISSING_INVALID_MAC_ADDRESS; + public String mac = ""; // Home ID of the bulb @Expose(serialize = false, deserialize = true) public int homeId; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java index a88399def71cc..c709c630188f2 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java @@ -38,7 +38,7 @@ public class SystemConfigResult { // The MAC address the response is coming from @Expose(serialize = true, deserialize = true) - public String mac = MISSING_INVALID_MAC_ADDRESS; + public String mac = ""; // Home ID of the bulb @Expose(serialize = true, deserialize = true) public int homeId; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java index fb810df7a3664..18cf557626869 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java @@ -53,7 +53,7 @@ public class WizResponse { // The MAC address the response is coming from @Expose(serialize = true, deserialize = true) - private String mac = MISSING_INVALID_MAC_ADDRESS; + private String mac = ""; // Whether or not a command succeeded (if the response is from a command) @Expose(serialize = true, deserialize = true) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index d2f3d889980a6..f8521a27dd27e 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -32,7 +32,7 @@ public class WizSyncState { // The MAC address the response is coming from @Expose(serialize = true, deserialize = true) - public String mac = MISSING_INVALID_MAC_ADDRESS; + public String mac = ""; // The current color mode of the bulb // We will assume by default that it's a single color bulb diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java index 799de0f95412c..2f84c67664a27 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java @@ -97,7 +97,7 @@ public void processReceivedPacket(final WizResponse receivedMessage) { String bulbIp = receivedMessage.getWizResponseIpAddress(); String bulbMac = receivedMessage.getWizResponseMacAddress(); - if (!bulbMac.equals(MISSING_INVALID_MAC_ADDRESS)) { + if (!bulbMac.isEmpty()) { @Nullable WizHandler handler = this.getHandlerRegisteredByMac(bulbMac); @@ -211,7 +211,7 @@ private String getMyMacAddress() { try { myMacAddress = NetworkUtils.getMyMacAddress(getMyIpAddress()); if (myMacAddress == null) { - logger.warn("No network interface could be found. MAC of OpenHab device is unknown."); + logger.warn("No network interface could be found. MAC of openHAB device is unknown."); return "OHMACAddress"; } } catch (Exception e) { @@ -222,7 +222,7 @@ private String getMyMacAddress() { } /** - * Returns a {@link RegistrationRequestParam} based on the current OpenHAB + * Returns a {@link RegistrationRequestParam} based on the current openHAB * connection. * */ diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java index 57912fcb9a043..ca7ac095b277e 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java @@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory; /** - * This Thread is responsible to receive all sync messages and redirect them to + * This Thread is responsible for receiving all sync messages and redirecting them to * {@link WizMediator}. * * @author Sriram Balakrishnan - Initial contribution diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java index 02b663d0642ad..7c0d499a89808 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java @@ -33,7 +33,6 @@ * @author Sara Geleskie Damiano - Initial contribution * */ - @NonNullByDefault public class WizColorConverter { @@ -145,10 +144,11 @@ public int[] hsbToRgbw(HSBType hsb) { * @param int green - the value of the green component (0-255) * @param int blue - the value of the blue component (0-255) * @param int white - the value of the white component (0-255) + * @param int dimming - the brightness of the bulb, independent of the RGB color (0-100) * * Totally made this up. * - * @return a {@link ColorRequestParam} with the color components + * @return a {@link HSBType} with the color components */ public HSBType rgbwDimmingToHSB(int red, int green, int blue, int white, int dimming) { // Can get hue from the ratios of the colors. diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java index 4ebf3d3e7b280..fadf622a4948d 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java @@ -39,10 +39,8 @@ * @author Sara Geleskie Damiano - Initial contribution * */ - @NonNullByDefault public class WizResponseDeserializer implements JsonDeserializer { - // We can't do too much logging, can we? private final Logger logger = LoggerFactory.getLogger(WizResponseDeserializer.class); @Override @@ -140,7 +138,7 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf } SystemConfigResult parsedFBParams = context.deserialize(jobject.getAsJsonObject("params"), SystemConfigResult.class); - if (parsedFBParams.mac == MISSING_INVALID_MAC_ADDRESS) { + if (parsedFBParams.mac.isEmpty()) { throw new JsonParseException("firstBeat received, but no MAC address present"); } deserializedResponse.setWizResponseMacAddress(parsedFBParams.mac); @@ -169,7 +167,7 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf } SystemConfigResult parsedCResult = context.deserialize(jobject.getAsJsonObject("result"), SystemConfigResult.class); - if (parsedCResult.mac == MISSING_INVALID_MAC_ADDRESS) { + if (parsedCResult.mac.isEmpty()) { throw new JsonParseException("getSystemConfig received, but no MAC address present"); } deserializedResponse.setWizResponseMacAddress(parsedCResult.mac); @@ -187,7 +185,7 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf } WizSyncState parsedPResult = context.deserialize(jobject.getAsJsonObject("result"), WizSyncState.class); - if (parsedPResult.mac == MISSING_INVALID_MAC_ADDRESS) { + if (parsedPResult.mac.isEmpty()) { throw new JsonParseException("getPilot received, but no MAC address present"); } deserializedResponse.setWizResponseMacAddress(parsedPResult.mac); @@ -205,7 +203,7 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf } WizSyncState parsedPParam = context.deserialize(jobject.getAsJsonObject("params"), WizSyncState.class); - if (parsedPParam.mac == MISSING_INVALID_MAC_ADDRESS) { + if (parsedPParam.mac.isEmpty()) { throw new JsonParseException("syncPilot received, but no MAC address present"); } deserializedResponse.setWizResponseMacAddress(parsedPParam.mac); diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index b6284ad3d5d5c..184eb304b9b0f 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -142,6 +142,7 @@ Number + Speed of the fan, in arbitrary steps From db8c95c3c9bf233574661a3ca37d3171ea3868d3 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 11 Nov 2024 08:36:23 -0700 Subject: [PATCH 15/26] Set Fan category for fan speed channel Signed-off-by: Cody Cutrer --- .../src/main/resources/OH-INF/thing/thing-types.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 184eb304b9b0f..d42e00cd0081f 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -143,6 +143,7 @@ Number Speed of the fan, in arbitrary steps + Fan From 30da083756bd9df6308d6e9ade9fc6b71e6abff1 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 14 Nov 2024 15:09:06 -0700 Subject: [PATCH 16/26] revert fan booleans to ints Signed-off-by: Cody Cutrer --- .../entities/FanModeRequestParam.java | 8 +++---- .../entities/FanReverseRequestParam.java | 8 +++---- .../entities/FanStateRequestParam.java | 8 +++---- .../wiz/internal/entities/WizSyncState.java | 6 +++--- .../wiz/internal/handler/WizHandler.java | 21 +++++++++++-------- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java index b4aa01dae9634..31cbbcdbf1845 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java @@ -24,17 +24,17 @@ @NonNullByDefault public class FanModeRequestParam implements Param { @Expose(serialize = true, deserialize = true) - private boolean fanMode; // true = 1, false = 0 + private int fanMode; // true = 1, false = 0 - public FanModeRequestParam(boolean fanMode) { + public FanModeRequestParam(int fanMode) { this.fanMode = fanMode; } - public boolean getFanMode() { + public int getFanMode() { return fanMode; } - public void setFanMode(boolean fanMode) { + public void setFanMode(int fanMode) { this.fanMode = fanMode; } } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java index be27426c57937..38a4d8e86c1ff 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java @@ -24,17 +24,17 @@ @NonNullByDefault public class FanReverseRequestParam implements Param { @Expose(serialize = true, deserialize = true) - private boolean fanRevrs; // true = 1, false = 0 + private int fanRevrs; // true = 1, false = 0 - public FanReverseRequestParam(boolean reverse) { + public FanReverseRequestParam(int reverse) { this.fanRevrs = reverse; } - public boolean getReverse() { + public int getReverse() { return fanRevrs; } - public void setReverse(boolean reverse) { + public void setReverse(int reverse) { this.fanRevrs = reverse; } } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java index e7471654e1b29..6978124ef85a0 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java @@ -24,17 +24,17 @@ @NonNullByDefault public class FanStateRequestParam implements Param { @Expose(serialize = true, deserialize = true) - private boolean fanState; // true = 1, false = 0 + private int fanState; // true = 1, false = 0 - public FanStateRequestParam(boolean fanState) { + public FanStateRequestParam(int fanState) { this.fanState = fanState; } - public boolean getFanState() { + public int getFanState() { return fanState; } - public void setFanState(boolean fanState) { + public void setFanState(int fanState) { this.fanState = fanState; } } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index f8521a27dd27e..b27e1f3e06ce8 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -95,13 +95,13 @@ public class WizSyncState { public int schdPsetId; @Expose(serialize = true, deserialize = true) - public boolean fanState; + public int fanState; @Expose(serialize = true, deserialize = true) public int fanSpeed; @Expose(serialize = true, deserialize = true) - public boolean fanMode; + public int fanMode; @Expose(serialize = true, deserialize = true) - public boolean fanRevrs; + public int fanRevrs; public WizColorMode getColorMode() { if (r != 0 || g != 0 || b != 0) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index d7c9e3c266af1..d97aa61a07242 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -311,8 +311,9 @@ private void handleOnOffCommand(OnOffType onOff) { } private void handleFanOnOffCommand(OnOffType onOff) { - setPilotCommand(new FanStateRequestParam(onOff == OnOffType.ON)); - mostRecentState.fanState = onOff == OnOffType.ON; + int value = onOff == OnOffType.ON ? 1 : 0; + setPilotCommand(new FanStateRequestParam(value)); + mostRecentState.fanState = value; } private void handleFanSpeedCommand(DecimalType speed) { @@ -321,13 +322,15 @@ private void handleFanSpeedCommand(DecimalType speed) { } private void handleFanReverseCommand(OnOffType onOff) { - setPilotCommand(new FanReverseRequestParam(onOff == OnOffType.ON)); - mostRecentState.fanRevrs = onOff == OnOffType.ON; + int value = onOff == OnOffType.ON ? 1 : 0; + setPilotCommand(new FanReverseRequestParam(value)); + mostRecentState.fanRevrs = value; } private void handleFanModeCommand(OnOffType onOff) { - setPilotCommand(new FanModeRequestParam(onOff == OnOffType.ON)); - mostRecentState.fanMode = onOff == OnOffType.ON; + int value = onOff == OnOffType.ON ? 1 : 0; + setPilotCommand(new FanModeRequestParam(value)); + mostRecentState.fanMode = value; } private void handleIncreaseDecreaseCommand(boolean isIncrease) { @@ -632,10 +635,10 @@ private void updateLightStatesFromParams(final WizSyncState receivedParam) { * @param receivedParam The received {@link WizSyncState} */ private void updateFanStatesFromParams(final WizSyncState receivedParam) { - updateFanState(CHANNEL_STATE, OnOffType.from(receivedParam.fanState)); + updateFanState(CHANNEL_STATE, receivedParam.fanState == 0 ? OnOffType.OFF : OnOffType.ON); updateFanState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); - updateFanState(CHANNEL_REVERSE, OnOffType.from(receivedParam.fanRevrs)); - updateFanState(CHANNEL_MODE, OnOffType.from(receivedParam.fanMode)); + updateFanState(CHANNEL_REVERSE, receivedParam.fanRevrs == 0 ? OnOffType.OFF : OnOffType.ON); + updateFanState(CHANNEL_MODE, receivedParam.fanMode == 0 ? OnOffType.OFF : OnOffType.ON); } /** From cfd24948e84c5fe456866dd90aa528654135e2e1 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Thu, 14 Nov 2024 15:11:23 -0700 Subject: [PATCH 17/26] serialize = true and deserialize = true are the defaults for @Expose so don't bother stating them. still leave the falses (even the double false, which could technically just not have an @Expose, to make it clear they're not part of the JSON) Signed-off-by: Cody Cutrer --- .../internal/entities/ColorRequestParam.java | 10 ++--- .../ColorTemperatureRequestParam.java | 2 +- .../entities/DimmingRequestParam.java | 2 +- .../entities/ErrorResponseResult.java | 4 +- .../entities/FanModeRequestParam.java | 2 +- .../entities/FanReverseRequestParam.java | 2 +- .../entities/FanSpeedRequestParam.java | 2 +- .../entities/FanStateRequestParam.java | 2 +- .../entities/FirstBeatResponseParam.java | 6 +-- .../internal/entities/ModelConfigResult.java | 2 +- .../internal/entities/PulseRequestParam.java | 4 +- .../entities/RegistrationRequestParam.java | 8 ++-- .../internal/entities/SceneRequestParam.java | 2 +- .../internal/entities/SpeedRequestParam.java | 2 +- .../internal/entities/StateRequestParam.java | 2 +- .../internal/entities/SystemConfigResult.java | 20 +++++----- .../wiz/internal/entities/WizRequest.java | 6 +-- .../wiz/internal/entities/WizResponse.java | 20 +++++----- .../wiz/internal/entities/WizSyncState.java | 38 +++++++++---------- 19 files changed, 68 insertions(+), 68 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java index 4d986b18fdc77..b2f7bb41e4af3 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorRequestParam.java @@ -31,15 +31,15 @@ */ @NonNullByDefault public class ColorRequestParam extends DimmingRequestParam { - @Expose(serialize = true, deserialize = true) + @Expose private int r; // red 0-255 - @Expose(serialize = true, deserialize = true) + @Expose private int g; // green 0-255 - @Expose(serialize = true, deserialize = true) + @Expose private int b; // blue 0-255 - @Expose(serialize = true, deserialize = true) + @Expose private int w; // warm white LED's 0-255 - @Expose(serialize = true, deserialize = true) + @Expose private int c; // cool white LED's 0-255 @Expose(serialize = false, deserialize = false) private WizColorConverter colorConverter = new WizColorConverter(); diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java index 3e07c6e0c2d39..ba0dd4faf5063 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ColorTemperatureRequestParam.java @@ -28,7 +28,7 @@ */ @NonNullByDefault public class ColorTemperatureRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private int temp; public ColorTemperatureRequestParam(int temp) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java index e33ab3bc2b6fc..64359cf059cb4 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/DimmingRequestParam.java @@ -31,7 +31,7 @@ */ @NonNullByDefault public class DimmingRequestParam extends StateRequestParam { - @Expose(serialize = true, deserialize = true) + @Expose private int dimming; public DimmingRequestParam(int dimming) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java index fa815cf7d2b44..d7d355ab4fdd8 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ErrorResponseResult.java @@ -31,8 +31,8 @@ */ @NonNullByDefault public class ErrorResponseResult { - @Expose(serialize = true, deserialize = true) + @Expose public int code; - @Expose(serialize = true, deserialize = true) + @Expose public @Nullable String message; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java index 31cbbcdbf1845..b7f3185c05994 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanModeRequestParam.java @@ -23,7 +23,7 @@ */ @NonNullByDefault public class FanModeRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private int fanMode; // true = 1, false = 0 public FanModeRequestParam(int fanMode) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java index 38a4d8e86c1ff..18788f33f1f26 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanReverseRequestParam.java @@ -23,7 +23,7 @@ */ @NonNullByDefault public class FanReverseRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private int fanRevrs; // true = 1, false = 0 public FanReverseRequestParam(int reverse) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java index 3642b1e6b8e98..1c090420a09b5 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanSpeedRequestParam.java @@ -23,7 +23,7 @@ */ @NonNullByDefault public class FanSpeedRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private int fanSpeed; // 0-6 public FanSpeedRequestParam(int fanSpeed) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java index 6978124ef85a0..049e48a9564db 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FanStateRequestParam.java @@ -23,7 +23,7 @@ */ @NonNullByDefault public class FanStateRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private int fanState; // true = 1, false = 0 public FanStateRequestParam(int fanState) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java index ee01cb2df41d7..1631dc626253e 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/FirstBeatResponseParam.java @@ -31,12 +31,12 @@ @NonNullByDefault public class FirstBeatResponseParam { // The MAC address the response is coming from - @Expose(serialize = true, deserialize = true) + @Expose public String mac = ""; // Home ID of the bulb - @Expose(serialize = false, deserialize = true) + @Expose(serialize = false) public int homeId; // Firmware version of the bulb - @Expose(serialize = true, deserialize = true) + @Expose public String fwVersion = LAST_KNOWN_FIRMWARE_VERSION; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java index aedfd8fc786d1..d52114d54c622 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/ModelConfigResult.java @@ -64,6 +64,6 @@ */ @NonNullByDefault public class ModelConfigResult { - @Expose(serialize = true, deserialize = true) + @Expose public int[] cctRange = {}; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java index 34d88a9277ef8..aa146a7554366 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/PulseRequestParam.java @@ -28,9 +28,9 @@ */ @NonNullByDefault public class PulseRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private int delta; - @Expose(serialize = true, deserialize = true) + @Expose private int duration; public PulseRequestParam(int delta, int duration) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java index d22e23237da99..e7dd90b7b8b86 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/RegistrationRequestParam.java @@ -32,15 +32,15 @@ */ @NonNullByDefault public class RegistrationRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private String phoneIp; - @Expose(serialize = true, deserialize = true) + @Expose private boolean register; // NOTE: We are NOT exposing the Home id for serialization because it's not // necessary and it's a PITA to find it - @Expose(serialize = false, deserialize = true) + @Expose(serialize = false) private int homeId; - @Expose(serialize = true, deserialize = true) + @Expose private String phoneMac; public RegistrationRequestParam(String phoneIp, boolean register, int homeId, String phoneMac) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java index 9e4a6d1c721a4..d0c5aa7301188 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SceneRequestParam.java @@ -28,7 +28,7 @@ */ @NonNullByDefault public class SceneRequestParam extends StateRequestParam { - @Expose(serialize = true, deserialize = true) + @Expose private int sceneId; public SceneRequestParam(int sceneId) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java index 05d14eb2187a4..568b9307a0367 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SpeedRequestParam.java @@ -31,7 +31,7 @@ */ @NonNullByDefault public class SpeedRequestParam extends SceneRequestParam { - @Expose(serialize = true, deserialize = true) + @Expose private int speed; public SpeedRequestParam(int sceneId, int speed) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java index 764dfc38a82ba..390bbc2626e09 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/StateRequestParam.java @@ -24,7 +24,7 @@ */ @NonNullByDefault public class StateRequestParam implements Param { - @Expose(serialize = true, deserialize = true) + @Expose private boolean state; // true = ON, false = OFF public StateRequestParam(boolean state) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java index c709c630188f2..638063cba044a 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/SystemConfigResult.java @@ -37,38 +37,38 @@ @NonNullByDefault public class SystemConfigResult { // The MAC address the response is coming from - @Expose(serialize = true, deserialize = true) + @Expose public String mac = ""; // Home ID of the bulb - @Expose(serialize = true, deserialize = true) + @Expose public int homeId; // The ID of room the bulb is assigned to - @Expose(serialize = true, deserialize = true) + @Expose public int roomId; // Not sure what the home lock is - @Expose(serialize = true, deserialize = true) + @Expose public boolean homeLock; // Also not sure about the pairing lock - @Expose(serialize = true, deserialize = true) + @Expose public boolean pairingLock; // Obviously a type ID // The value is 0 for both BR30 and A19 full color bulbs - @Expose(serialize = true, deserialize = true) + @Expose public int typeId; // The module name // The value is "ESP01_SHRGB1C_31" for both BR30 and A19 full color bulbs - @Expose(serialize = true, deserialize = true) + @Expose public String moduleName = EXPECTED_MODULE_NAME; // Firmware version of the bulb - @Expose(serialize = true, deserialize = true) + @Expose public String fwVersion = LAST_KNOWN_FIRMWARE_VERSION; // The ID of group the bulb is assigned to // I don't know how to group bulbs, all of mine return 0 - @Expose(serialize = true, deserialize = true) + @Expose public int groupId; // Not sure what the numbers mean // For a full color A19 I get [33,1] // For a full coloer BR30 I get [37,1] - @Expose(serialize = true, deserialize = true) + @Expose public int[] drvConf = {}; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java index 5dae512e77838..c98d76fba16c4 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizRequest.java @@ -26,16 +26,16 @@ */ @NonNullByDefault public class WizRequest { - @Expose(serialize = true, deserialize = true) + @Expose private int id; - @Expose(serialize = true, deserialize = true) + @Expose private WizMethodType method; @Expose(serialize = false, deserialize = false) private String methodName; - @Expose(serialize = true, deserialize = false) + @Expose(deserialize = false) private @Nullable Param params; /** diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java index 18cf557626869..000c9ab2dc6ab 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java @@ -30,41 +30,41 @@ public class WizResponse { // The IP address we're coming from - @Expose(serialize = false, deserialize = true) + @Expose(deserialize = true) private String wizResponseIpAddress = ""; // Increasing numeric value. // Bulb doesn't seem to care if it receives the same id multiple time // or commands with lower numbers after higher ones. - @Expose(serialize = true, deserialize = true) + @Expose private int id; // Not sure what env is - value always seems to be "pro" - @Expose(serialize = true, deserialize = true) + @Expose private @Nullable String env; // An error response - @Expose(serialize = true, deserialize = true) + @Expose private @Nullable ErrorResponseResult methodError; // The method being used - see the enum for details // We're setting this to "unknown" - @Expose(serialize = true, deserialize = true) + @Expose private WizMethodType method = WizMethodType.UnknownMethod; // The MAC address the response is coming from - @Expose(serialize = true, deserialize = true) + @Expose private String mac = ""; // Whether or not a command succeeded (if the response is from a command) - @Expose(serialize = true, deserialize = true) + @Expose private boolean success = false; // The system configuration result, if present - @Expose(serialize = true, deserialize = true) + @Expose private @Nullable SystemConfigResult systemConfigResult; // The modeul configuration result, if present - @Expose(serialize = true, deserialize = true) + @Expose private @Nullable ModelConfigResult modelConfigResult; // The parameters or result of a command/response @@ -72,7 +72,7 @@ public class WizResponse { // "params" is retuned with an unsolicited sync/heartbeat. The result returned // from a get method is generally identical to the params returned in the // heartbeat. - @Expose(serialize = true, deserialize = true) + @Expose private @Nullable WizSyncState params; /** diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index b27e1f3e06ce8..e9ceee213a8c3 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -31,7 +31,7 @@ @NonNullByDefault public class WizSyncState { // The MAC address the response is coming from - @Expose(serialize = true, deserialize = true) + @Expose public String mac = ""; // The current color mode of the bulb @@ -46,7 +46,7 @@ public class WizSyncState { */ // Not sure exactly what this means, seems to be a boolean // I believe the bulb communicates with the WiZ servers via MQTT - @Expose(serialize = true, deserialize = true) + @Expose public int mqttCd; /* @@ -54,53 +54,53 @@ public class WizSyncState { */ // The bulb's WiFi signal strength - @Expose(serialize = true, deserialize = true) + @Expose public int rssi; // The overall state of the bulb - on/off - @Expose(serialize = true, deserialize = true) + @Expose public boolean state; // The numeric identifier for a preset lighting mode - @Expose(serialize = true, deserialize = true) + @Expose public int sceneId; // Unknown - not seen by SRGD - @Expose(serialize = true, deserialize = true) + @Expose public boolean play; // The speed of color changes in dynamic lighting modes - @Expose(serialize = true, deserialize = true) + @Expose public int speed; // Strength of the red channel (0-255) - @Expose(serialize = true, deserialize = true) + @Expose public int r; // Strength of the green channel (0-255) - @Expose(serialize = true, deserialize = true) + @Expose public int g; // Strength of the blue channel (0-255) - @Expose(serialize = true, deserialize = true) + @Expose public int b; // Intensity of the cool white channel (0-255) - @Expose(serialize = true, deserialize = true) + @Expose public int c; // Intensity of the warm white channel (0-255) - @Expose(serialize = true, deserialize = true) + @Expose public int w; // Dimming percent (10-100) - @Expose(serialize = true, deserialize = true) + @Expose public int dimming; // Color temperature - sent in place of r/g/b/c/w // If temperatures are sent, color LED's are not in use - @Expose(serialize = true, deserialize = true) + @Expose public int temp; // Indicates if the light mode is applied following a pre-set "rhythm" - @Expose(serialize = true, deserialize = true) + @Expose public int schdPsetId; - @Expose(serialize = true, deserialize = true) + @Expose public int fanState; - @Expose(serialize = true, deserialize = true) + @Expose public int fanSpeed; - @Expose(serialize = true, deserialize = true) + @Expose public int fanMode; - @Expose(serialize = true, deserialize = true) + @Expose public int fanRevrs; public WizColorMode getColorMode() { From e27528e69fe3a40db7f718959ed724c2945bdde9 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Sun, 17 Nov 2024 04:41:59 -0700 Subject: [PATCH 18/26] add missing signal-strength and last-update channels to fan thing Signed-off-by: Cody Cutrer --- .../src/main/resources/OH-INF/thing/thing-types.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index d42e00cd0081f..fd2cfb1707d7d 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -70,6 +70,8 @@ + + From 2afe79cd1586bc092739c573f864851e8daf25ee Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Sun, 17 Nov 2024 04:43:58 -0700 Subject: [PATCH 19/26] use fan-with-bulb thing when autodiscovering so a fan-only thing would need to be manually created Signed-off-by: Cody Cutrer --- .../binding/wiz/internal/discovery/WizDiscoveryService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java index 82232d95ac0b5..4ce1ef82b1f85 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java @@ -194,7 +194,7 @@ public void discoveredLight(final String macAddress, final String ipAddress) { // Check for "FANDIMS" as in confirmed example ESP03_FANDIMS_31 for Faro Barcelona Smart Fan } else if (discoveredModel.contains("FANDIMS")) { - thisDeviceType = THING_TYPE_FAN; + thisDeviceType = THING_TYPE_FAN_WITH_DIMMABLE_BULB; thisDeviceLabel = "WiZ Smart Fan at " + ipAddress; newThingId = new ThingUID(thisDeviceType, macAddress); logger.trace("New device appears to be a smart fan and will be given the UUID: {}", newThingId); From 19ec6894ac0d0031743660b2fc2cd8832de2811f Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Sun, 17 Nov 2024 04:48:34 -0700 Subject: [PATCH 20/26] make fan mode an integer since it's 1/2, not 0/1, and theoretically more could be added Signed-off-by: Cody Cutrer --- .../binding/wiz/internal/handler/WizHandler.java | 13 ++++++------- .../src/main/resources/OH-INF/thing/thing-types.xml | 8 ++++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index d97aa61a07242..6f223b7abda89 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -228,8 +228,8 @@ private void handleFanCommand(final String channelId, final Command command) { } break; case CHANNEL_MODE: - if (command instanceof OnOffType onOffCommand) { - handleFanModeCommand(onOffCommand); + if (command instanceof DecimalType decimalCommand) { + handleFanModeCommand(decimalCommand); } break; case CHANNEL_SPEED: @@ -327,10 +327,9 @@ private void handleFanReverseCommand(OnOffType onOff) { mostRecentState.fanRevrs = value; } - private void handleFanModeCommand(OnOffType onOff) { - int value = onOff == OnOffType.ON ? 1 : 0; - setPilotCommand(new FanModeRequestParam(value)); - mostRecentState.fanMode = value; + private void handleFanModeCommand(DecimalType mode) { + setPilotCommand(new FanModeRequestParam(mode.intValue())); + mostRecentState.fanMode = mode.intValue(); } private void handleIncreaseDecreaseCommand(boolean isIncrease) { @@ -638,7 +637,7 @@ private void updateFanStatesFromParams(final WizSyncState receivedParam) { updateFanState(CHANNEL_STATE, receivedParam.fanState == 0 ? OnOffType.OFF : OnOffType.ON); updateFanState(CHANNEL_SPEED, new DecimalType(receivedParam.fanSpeed)); updateFanState(CHANNEL_REVERSE, receivedParam.fanRevrs == 0 ? OnOffType.OFF : OnOffType.ON); - updateFanState(CHANNEL_MODE, receivedParam.fanMode == 0 ? OnOffType.OFF : OnOffType.ON); + updateFanState(CHANNEL_MODE, new DecimalType(receivedParam.fanMode)); } /** diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index fd2cfb1707d7d..454d1a39c42f5 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -94,7 +94,7 @@ Lighting - + @@ -161,12 +161,12 @@ - Switch + Number - - + + From 98d9bd614067137fc644d668507e7047b6fa3b35 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Mon, 25 Nov 2024 08:43:27 -0700 Subject: [PATCH 21/26] correct state updates for fan+light Signed-off-by: Cody Cutrer --- .../org/openhab/binding/wiz/internal/handler/WizHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 6f223b7abda89..10975a3359a83 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -851,7 +851,7 @@ private void updateFanState(String channelId, State state) { if (isFanOnly) { updateState(channelId, state); } else { - updateState(new ChannelUID(this.getThing().getUID(), CHANNEL_GROUP_LIGHT, channelId), state); + updateState(new ChannelUID(this.getThing().getUID(), CHANNEL_GROUP_FAN, channelId), state); } } From 6a313570b9b5c7cf30f302eee422af07b5414eb8 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 3 Dec 2024 09:09:59 -0700 Subject: [PATCH 22/26] add rssi advanced channel Number:Dimensionless with unit dB also mark last-update as advanced - most people don't care about it Signed-off-by: Cody Cutrer --- .../wiz/internal/WizBindingConstants.java | 1 + .../binding/wiz/internal/handler/WizHandler.java | 1 + .../main/resources/OH-INF/thing/thing-types.xml | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java index 825f528d05d1b..d3ffd29364a27 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizBindingConstants.java @@ -57,6 +57,7 @@ public class WizBindingConstants { public static final String CHANNEL_LAST_UPDATE = "last-update"; public static final String CHANNEL_MODE = "mode"; public static final String CHANNEL_REVERSE = "reverse"; + public static final String CHANNEL_RSSI = "rssi"; public static final String CHANNEL_SIGNAL_STRENGTH = "signal-strength"; public static final String CHANNEL_SPEED = "speed"; public static final String CHANNEL_STATE = "state"; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 10975a3359a83..567096c491787 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -577,6 +577,7 @@ private synchronized void updateStatesFromParams(final WizSyncState receivedPara strength = 4; } updateDeviceState(CHANNEL_SIGNAL_STRENGTH, new DecimalType(strength)); + updateDeviceState(CHANNEL_RSSI, new QuantityType<>(receivedParam.rssi, Units.DECIBEL)); } } diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml index 454d1a39c42f5..9b6b103643dc4 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/thing/thing-types.xml @@ -15,6 +15,7 @@ + @@ -31,6 +32,7 @@ + @@ -45,6 +47,7 @@ + @@ -57,6 +60,7 @@ + @@ -72,6 +76,7 @@ + @@ -171,7 +176,7 @@ - + DateTime Timestamp of last status update @@ -179,11 +184,20 @@ + + Number:Dimensionless + + WiFi Received Signal Strength Indicator + QualityOfService + + + + From 8f2541c19b53c631054a54041999516e7e620cee Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 3 Dec 2024 09:12:23 -0700 Subject: [PATCH 23/26] remove unused imports Signed-off-by: Cody Cutrer --- .../org/openhab/binding/wiz/internal/entities/WizResponse.java | 2 -- .../org/openhab/binding/wiz/internal/entities/WizSyncState.java | 2 -- .../binding/wiz/internal/utils/WizResponseDeserializer.java | 2 -- 3 files changed, 6 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java index 000c9ab2dc6ab..1801c8b2989b6 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizResponse.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wiz.internal.WizBindingConstants.*; - import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.wiz.internal.enums.WizMethodType; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java index e9ceee213a8c3..de6421b8dfe0a 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/entities/WizSyncState.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.wiz.internal.entities; -import static org.openhab.binding.wiz.internal.WizBindingConstants.*; - import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.wiz.internal.enums.WizColorMode; import org.openhab.binding.wiz.internal.utils.WizColorConverter; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java index fadf622a4948d..468fd5f3a6ebe 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.wiz.internal.utils; -import static org.openhab.binding.wiz.internal.WizBindingConstants.*; - import java.lang.reflect.Type; import org.eclipse.jdt.annotation.NonNullByDefault; From f91b7298b6ed66ccd65205db0c8eaf2e7b4150b0 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Tue, 3 Dec 2024 10:19:21 -0700 Subject: [PATCH 24/26] address review comments mostly adjusting error handling, especially wrt not being able to find openHAB's IP address or MAC address Signed-off-by: Cody Cutrer --- bundles/org.openhab.binding.wiz/README.md | 36 +++++---- .../wiz/internal/WizHandlerFactory.java | 3 +- .../discovery/WizDiscoveryService.java | 6 +- .../wiz/internal/handler/WizHandler.java | 32 +++++--- .../wiz/internal/handler/WizMediator.java | 2 +- .../wiz/internal/handler/WizMediatorImpl.java | 44 ++++------- .../runnable/WizUpdateReceiverRunnable.java | 2 +- .../wiz/internal/utils/NetworkUtils.java | 28 ++++--- .../wiz/internal/utils/ValidationUtils.java | 10 --- .../wiz/internal/utils/WizColorConverter.java | 73 +++---------------- .../internal/utils/WizPacketConverter.java | 3 +- .../utils/WizResponseDeserializer.java | 6 +- .../main/resources/OH-INF/i18n/wiz.properties | 7 +- 13 files changed, 100 insertions(+), 152 deletions(-) diff --git a/bundles/org.openhab.binding.wiz/README.md b/bundles/org.openhab.binding.wiz/README.md index a12e2f56a4f2c..55d2816f61d3d 100644 --- a/bundles/org.openhab.binding.wiz/README.md +++ b/bundles/org.openhab.binding.wiz/README.md @@ -24,7 +24,7 @@ Local control must also be enabled with-in the WiZ app in the app settings. - WiZ Smart Plugs - Smart fans (with or without a dimmable light) -_Note_ This binding was created for and tested on the full color with tunable white bulbs, however, users have reported success with other bulb types and plugs. +**NOTE:** This binding was created for and tested on the full color with tunable white bulbs, however, users have reported success with other bulb types and plugs. ## Discovery @@ -72,19 +72,25 @@ Thing wiz:bulb:lamp "My Lamp" @ "Living Room" [ macAddress="accf23343cxx", ipAdd ## Channels -The binding supports the following channels: - -| Channel ID | Item Type | Description | Access | -|-----------------|--------------------|-------------------------------------------------------|--------| -| color | Color | State, intensity, and color of the LEDs | R/W | -| temperature | Dimmer | Color temperature of the bulb | R/W | -| temperature-abs | Number:Temperature | Color temperature of the bulb in Kelvin | R/W | -| brightness | Dimmer | The brightness of the bulb | R/W | -| state | Switch | Whether the bulb is on or off | R/W | -| light-mode | Number | Preset light mode name to run | R/W | -| speed | Dimmer | Speed of the color changes in dynamic light modes | R/W | -| signal-strength | Number | Quality of the bulb's WiFi connection | R | -| last-update | Time | The last time an an update was received from the bulb | R | +The binding supports the following channels. If a device is only a light or only a fan, the channels will +not be in a group. + +| Channel ID | Item Type | Description | Access | +|------------------------|----------------------|-------------------------------------------------------|--------| +| light#color | Color | State, intensity, and color of the LEDs | R/W | +| light#temperature | Dimmer | Color temperature of the bulb | R/W | +| light#temperature-abs | Number:Temperature | Color temperature of the bulb in Kelvin | R/W | +| light#brightness | Dimmer | The brightness of the bulb | R/W | +| light#state | Switch | Whether the bulb is on or off | R/W | +| light#light-mode | Number | Preset light mode name to run | R/W | +| light#speed | Dimmer | Speed of the color changes in dynamic light modes | R/W | +| fan#state | Switch | Whether the fan is on or off | R/W | +| fan#speed | Number | Speed of the fan, in arbitrary steps | R/W | +| fan#reverse | Switch | Whether the fan direction is reversed | R/W | +| fan#mode | Number | Special fan modes (Breeze) | R/W | +| device#last-update | Time | The last time an an update was received from the bulb | R | +| device#signal-strength | Number | Quality of the bulb's WiFi connection | R | +| device#rssi | Number:Dimensionless | WiFi Received Signal Strength Indicator (in dB) | R | ## Light Modes @@ -137,7 +143,7 @@ Sending a command on the color channel or the temperature channel will cause the - Fade in/out times are configured in the app. - Sending too many commands to the bulbs too quickly can cause them to stop responding for a period of time. -## Example item linked to a channel +## Example Item Linked To a Channel ```java Color LivingRoom_Light_Color "Living Room Lamp" (gLivingroom) {channel="wiz:color-bulb:accf23343cxx:color"} diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java index 79fa4e67c7806..d15abedfb0075 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/WizHandlerFactory.java @@ -66,8 +66,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { if (supportsThingType(thing.getThingTypeUID())) { WizHandler handler; - handler = new WizHandler(thing, this.mediator.getRegistrationParams(), stateDescriptionProvider, - timeZoneProvider); + handler = new WizHandler(thing, mediator, stateDescriptionProvider, timeZoneProvider); mediator.registerThingAndWizBulbHandler(thing, handler); return handler; diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java index 4ce1ef82b1f85..6f980523be433 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/discovery/WizDiscoveryService.java @@ -27,6 +27,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wiz.internal.entities.RegistrationRequestParam; import org.openhab.binding.wiz.internal.entities.SystemConfigResult; import org.openhab.binding.wiz.internal.entities.WizRequest; import org.openhab.binding.wiz.internal.entities.WizResponse; @@ -116,7 +117,8 @@ protected void startScan() { String broadcastIp = this.mediator.getNetworkAddressService().getConfiguredBroadcastAddress(); if (broadcastIp != null) { InetAddress address = InetAddress.getByName(broadcastIp); - WizRequest request = new WizRequest(WizMethodType.Registration, this.mediator.getRegistrationParams()); + RegistrationRequestParam registrationRequestParam = mediator.getRegistrationParams(); + WizRequest request = new WizRequest(WizMethodType.Registration, registrationRequestParam); request.setId(0); byte[] message = this.converter.transformToByteMessage(request); @@ -133,6 +135,8 @@ protected void startScan() { } else { logger.warn("No broadcast address was configured or discovered! No broadcast sent."); } + } catch (IllegalStateException e) { + logger.debug("Unable to start background scan: {}", e.getMessage()); } catch (IOException exception) { logger.debug("Something wrong happened when broadcasting the packet to port {}... msg: {}", DEFAULT_UDP_PORT, exception.getMessage()); diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 567096c491787..6befaea444d06 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -93,7 +93,7 @@ public class WizHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(WizHandler.class); private @NonNullByDefault({}) WizDeviceConfiguration config; - private RegistrationRequestParam registrationInfo; + private @Nullable RegistrationRequestParam registrationRequestParam; private int homeId; private WizSyncState mostRecentState; @@ -120,10 +120,14 @@ public class WizHandler extends BaseThingHandler { * @param thing the thing of the handler. * @param stateDescriptionProvider A state description provider */ - public WizHandler(final Thing thing, final RegistrationRequestParam registrationPacket, + public WizHandler(final Thing thing, final WizMediator mediator, WizStateDescriptionProvider stateDescriptionProvider, TimeZoneProvider timeZoneProvider) { super(thing); - this.registrationInfo = registrationPacket; + try { + registrationRequestParam = mediator.getRegistrationParams(); + } catch (IllegalStateException e) { + registrationRequestParam = null; + } this.stateDescriptionProvider = stateDescriptionProvider; this.timeZoneProvider = timeZoneProvider; this.mostRecentState = new WizSyncState(); @@ -334,7 +338,7 @@ private void handleFanModeCommand(DecimalType mode) { private void handleIncreaseDecreaseCommand(boolean isIncrease) { int oldDimming = mostRecentState.dimming; - int newDimming = 50; + int newDimming; if (isIncrease) { newDimming = Math.min(100, oldDimming + 5); } else { @@ -351,7 +355,7 @@ private void handleTemperatureCommand(int temperature) { private void handleIncreaseDecreaseTemperatureCommand(boolean isIncrease) { float oldTempPct = colorTempToPercent(mostRecentState.getTemperature()).floatValue(); - float newTempPct = 50; + float newTempPct; if (isIncrease) { newTempPct = Math.min(100, oldTempPct + 5); } else { @@ -370,7 +374,7 @@ private void handleSpeedCommand(PercentType speed) { private void handleIncreaseDecreaseSpeedCommand(boolean isIncrease) { int oldSpeed = mostRecentState.speed; - int newSpeed = 50; + int newSpeed; if (isIncrease) { newSpeed = Math.min(100, oldSpeed + 5); } else { @@ -452,11 +456,18 @@ public void initialize() { fullyInitialized = false; disposed = false; - // set the thing status to UNKNOWN temporarily - updateStatus(ThingStatus.UNKNOWN); - if (ValidationUtils.isMacNotValid(config.macAddress)) { + if (registrationRequestParam == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Unable to determine openHAB's IP or MAC address"); + return; + } + if (!ValidationUtils.isMacValid(config.macAddress)) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "MAC address is not valid"); + return; } + + // set the thing status to UNKNOWN temporarily + updateStatus(ThingStatus.UNKNOWN); updateDeviceProperties(); initGetStatusAndKeepAliveThread(); fullyInitialized = true; @@ -792,7 +803,8 @@ private synchronized void updateDeviceProperties() { * heart-beats the registration must be re-sent after 30s. */ private synchronized void registerWithDevice() { - WizResponse registrationResponse = sendRequestPacket(WizMethodType.Registration, this.registrationInfo); + WizResponse registrationResponse = sendRequestPacket(WizMethodType.Registration, + Objects.requireNonNull(registrationRequestParam)); if (registrationResponse != null) { if (registrationResponse.getResultSuccess()) { updateTimestamps(); diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java index bc9ed8169f510..29ee6ff6fc774 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediator.java @@ -45,7 +45,7 @@ public interface WizMediator { * connection. * */ - RegistrationRequestParam getRegistrationParams(); + RegistrationRequestParam getRegistrationParams() throws IllegalStateException; /** * Registers a new {@link Thing} and the corresponding diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java index 2f84c67664a27..c354df448f779 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizMediatorImpl.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.wiz.internal.WizBindingConstants; import org.openhab.binding.wiz.internal.discovery.WizDiscoveryService; import org.openhab.binding.wiz.internal.entities.RegistrationRequestParam; import org.openhab.binding.wiz.internal.entities.WizResponse; @@ -175,10 +176,10 @@ private void initMediatorWizBulbUpdateReceiverRunnable() { try { logger.trace("Receiver thread is either null, interrupted, or dead."); WizUpdateReceiverRunnable newReceiver = new WizUpdateReceiverRunnable(this, DEFAULT_LISTENER_UDP_PORT); - Thread newThread = new Thread(newReceiver); + Thread newThread = new Thread(newReceiver, + "OH-binding-" + WizBindingConstants.BINDING_ID + "-ReceiverThread"); newThread.setDaemon(true); newThread.start(); - newThread.setName("wizReceiverThread"); this.receiver = newReceiver; this.receiverThread = newThread; } catch (SocketException e) { @@ -197,37 +198,22 @@ public Set getAllThingsRegistered() { return this.handlersRegisteredByThing.keySet(); } - private String getMyIpAddress() { - String myIpAddress = networkAddressService.getPrimaryIpv4HostAddress(); - if (myIpAddress == null) { - logger.warn("Network interface did not return an IP address!"); - return "OHIPAddress"; - } - return myIpAddress; - } - - private String getMyMacAddress() { - String myMacAddress; - try { - myMacAddress = NetworkUtils.getMyMacAddress(getMyIpAddress()); - if (myMacAddress == null) { - logger.warn("No network interface could be found. MAC of openHAB device is unknown."); - return "OHMACAddress"; - } - } catch (Exception e) { - logger.warn("MAC Address of openHAB device is invalid."); - return "OHMACAddress"; - } - return myMacAddress; - } - /** * Returns a {@link RegistrationRequestParam} based on the current openHAB * connection. - * + * + * @throws IllegalStateException */ - public RegistrationRequestParam getRegistrationParams() { - return new RegistrationRequestParam(getMyIpAddress(), true, 0, getMyMacAddress()); + public RegistrationRequestParam getRegistrationParams() throws IllegalStateException { + String ipAddress = networkAddressService.getPrimaryIpv4HostAddress(); + String macAddress = null; + if (ipAddress != null) { + macAddress = NetworkUtils.getMacAddress(ipAddress); + } + if (ipAddress == null || macAddress == null) { + throw new IllegalStateException("Unable to determine openHAB's IP and/or MAC address"); + } + return new RegistrationRequestParam(ipAddress, true, 0, macAddress); } @Override diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java index ca7ac095b277e..0946a5168b392 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/runnable/WizUpdateReceiverRunnable.java @@ -125,7 +125,7 @@ private void datagramSocketHealthRoutine() { this.datagramSocket = dsocket; logger.trace("Datagram Socket reconnected."); } catch (SocketException exception) { - logger.warn("Problem creating one new socket on port {}. Error: {}", listeningPort, + logger.debug("Problem creating one new socket on port {}. Error: {}", listeningPort, exception.getLocalizedMessage()); } } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java index a1ec9c5e77f55..1987c5c24eecc 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/NetworkUtils.java @@ -15,7 +15,6 @@ import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; -import java.rmi.UnknownHostException; import java.util.Enumeration; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -34,25 +33,24 @@ public final class NetworkUtils { * Returns the MAC address of the openHAB first network device. * * @return The MAC address of the openHAB network device. - * @throws UnknownHostException - * @throws SocketException */ - public static @Nullable String getMyMacAddress(String matchIP) throws UnknownHostException, SocketException { - String macAddress = null; - Enumeration networks = NetworkInterface.getNetworkInterfaces(); - while (networks.hasMoreElements()) { - NetworkInterface network = networks.nextElement(); + public static @Nullable String getMacAddress(String matchIP) { + try { + Enumeration networks = NetworkInterface.getNetworkInterfaces(); + while (networks.hasMoreElements()) { + NetworkInterface network = networks.nextElement(); - if (networkMatchesIP(network, matchIP)) { - byte[] hardwareAddress = network.getHardwareAddress(); - if (hardwareAddress == null) { - continue; + if (networkMatchesIP(network, matchIP)) { + byte[] hardwareAddress = network.getHardwareAddress(); + if (hardwareAddress == null) { + continue; + } + return convertBytesToMACString(hardwareAddress); } - macAddress = convertBytesToMACString(hardwareAddress); - break; // Short circuit if we found it } + } catch (SocketException e) { } - return macAddress; + return null; } private static boolean networkMatchesIP(NetworkInterface network, String ip) { diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java index f40f2cc20415a..5ae40af4d3183 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/ValidationUtils.java @@ -43,14 +43,4 @@ public static boolean isMacValid(final String mac) { Matcher matcher = VALID_PATTERN.matcher(mac); return matcher.matches(); } - - /** - * Validates if one Mac address is not valid. - * - * @param mac the mac, with or without : - * @return true if is not valid. - */ - public static boolean isMacNotValid(final String macAddress) { - return !isMacValid(macAddress); - } } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java index 7c0d499a89808..75423fad37e3f 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizColorConverter.java @@ -16,11 +16,10 @@ import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.PercentType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.openhab.core.util.ColorUtil; /** - * Utilities for converting colors and color temperures + * Utilities for converting colors and color temperatures * * The full color WiZ bulbs can produce colors and various temperatures of * "whites" by mixing any of the available LEDs: RGBWwarm = RGBWWCwarm = Red, @@ -35,9 +34,6 @@ */ @NonNullByDefault public class WizColorConverter { - - private final Logger logger = LoggerFactory.getLogger(WizColorConverter.class); - /** * Converts an {@link DecimalType} hue and a {@link PercentType} saturation to * red, green, blue, and white (RGBW) components. Because the WiZ bulbs keep @@ -52,65 +48,20 @@ public class WizColorConverter { * @return an interger array of the color components */ public int[] hsbToRgbw(HSBType hsb) { - double redD = 255.; - double greenD = 255.; - double blueD = 255.; - int red = 255; - int green = 255; - int blue = 255; - int white = 255; - // Since we're going to use the white lights to control saturation, recalculate what // the HSBvalue would be if the color was at full brightness and saturation - Double hue = hsb.getHue().doubleValue(); - Double sat255 = ((hsb.getSaturation().doubleValue()) / 100) * 255; - - if (sat255 > 0) { - int i = (int) (hue / 60); // color quadrant 0..2555 - double f = hue % 60; // 0..59 - double q = 255 - ((f / 60) * sat255); - - double p = 0; - double t = 255 - (((60 - f) / 60) * 255); - - switch (i) { - case 0: - // redD = 255; - greenD = t; - blueD = p; - break; - case 1: - redD = q; - // greenD = 255; - blueD = p; - break; - case 2: - redD = p; - // greenD = 255; - blueD = t; - break; - case 3: - redD = p; - greenD = q; - // blueD = 255; - break; - case 4: - redD = t; - greenD = p; - // blueD = 255; - break; - default: - // redD = 255; - greenD = p; - blueD = q; - break; - } - } + HSBType hsbFullBrightness = new HSBType(hsb.getHue(), hsb.getSaturation(), PercentType.HUNDRED); + PercentType[] rgbPercent = ColorUtil.hsbToRgbPercent(hsbFullBrightness); + double redD = rgbPercent[0].doubleValue(); + double greenD = rgbPercent[1].doubleValue(); + double blueD = rgbPercent[2].doubleValue(); - logger.debug("Colors from hue, assuming full brightness R: {} G: {} B: {}", redD, greenD, blueD); + double saturationPercent = hsb.getSaturation().doubleValue() / 100; - // Convert the "PercentType" to a percent - double saturationPercent = (hsb.getSaturation().doubleValue() / 100); + int red; + int green; + int blue; + int white; // Calculate the white intensity from saturation and adjust down the other colors // This is approximately what the WiZ app does. Personally, I think it undersaturates everything diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java index 414f2e3c45a2b..400745dd43b9b 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java @@ -47,7 +47,6 @@ public WizPacketConverter() { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(WizResponse.class, new WizResponseDeserializer()); gsonBuilder.excludeFieldsWithoutExposeAnnotation(); - // gsonBuilder.setLenient(); Gson gson = gsonBuilder.create(); this.wizGsonBuilder = gson; } @@ -85,7 +84,7 @@ public byte[] transformToByteMessage(final WizRequest requestPacket) { response = this.wizGsonBuilder.fromJson(responseJson, WizResponse.class); response.setWizResponseIpAddress(packet.getAddress().getHostAddress()); } catch (JsonParseException e) { - logger.error("Error parsing json! {}", e.getMessage()); + logger.debug("Error parsing json! {}", e.getMessage()); } return response; } diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java index 468fd5f3a6ebe..6cfc24ad85d34 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizResponseDeserializer.java @@ -73,10 +73,10 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf ErrorResponseResult.class); deserializedResponse.setError(error); if (jobject.has("method")) { - logger.warn("Bulb returned an error on method {}: {}, {}", jobject.get("method"), error.code, + logger.debug("Bulb returned an error on method {}: {}, {}", jobject.get("method"), error.code, error.message); } else { - logger.warn("Bulb returned an error: {}", error.code); + logger.debug("Bulb returned an error: {}", error.code); } return deserializedResponse; } @@ -91,7 +91,7 @@ public WizResponse deserialize(@Nullable JsonElement json, @Nullable Type typeOf method = WizMethodType.valueOf(properCaseMethod); deserializedResponse.setMethod(method); } catch (IllegalArgumentException e) { - logger.warn("Bulb returned an invalid method: {}", jobject.get("method")); + logger.debug("Bulb returned an invalid method: {}", jobject.get("method")); return deserializedResponse; } } else { diff --git a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties index 95c3deeaca950..620005071a551 100644 --- a/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties +++ b/bundles/org.openhab.binding.wiz/src/main/resources/OH-INF/i18n/wiz.properties @@ -40,12 +40,13 @@ channel-group-type.wiz.fan-group.label = Fan # channel types channel-type.wiz.fan-mode.label = Mode -channel-type.wiz.fan-mode.state.option.OFF = Normal -channel-type.wiz.fan-mode.state.option.ON = Breeze +channel-type.wiz.fan-mode.state.option.1 = Normal +channel-type.wiz.fan-mode.state.option.2 = Breeze channel-type.wiz.fan-reverse.label = Reverse channel-type.wiz.fan-reverse.state.option.OFF = Forward channel-type.wiz.fan-reverse.state.option.ON = Reverse channel-type.wiz.fan-speed.label = Fan Speed +channel-type.wiz.fan-speed.description = Speed of the fan, in arbitrary steps channel-type.wiz.last-update.label = Last Update channel-type.wiz.last-update.description = Timestamp of last status update channel-type.wiz.light-mode-speed.label = Dynamic Light Mode Speed @@ -83,6 +84,8 @@ channel-type.wiz.light-mode.state.option.29 = Candlelight channel-type.wiz.light-mode.state.option.30 = Golden White channel-type.wiz.light-mode.state.option.31 = Pulse channel-type.wiz.light-mode.state.option.32 = Steampunk +channel-type.wiz.rssi.label = RSSI +channel-type.wiz.rssi.description = WiFi Received Signal Strength Indicator # thing types config From be801c5fab42a1ef89945e52a01371dd6560a4c8 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Wed, 4 Dec 2024 08:12:26 -0700 Subject: [PATCH 25/26] treat fan speed command of 0 as OFF Signed-off-by: Cody Cutrer --- .../openhab/binding/wiz/internal/handler/WizHandler.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java index 6befaea444d06..1b91a47ebf7f0 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/handler/WizHandler.java @@ -238,7 +238,11 @@ private void handleFanCommand(final String channelId, final Command command) { break; case CHANNEL_SPEED: if (command instanceof DecimalType numberCommand) { - handleFanSpeedCommand(numberCommand); + if (numberCommand.equals(DecimalType.ZERO)) { + handleFanOnOffCommand(OnOffType.OFF); + } else { + handleFanSpeedCommand(numberCommand); + } } break; case CHANNEL_REVERSE: From 2aa75b47c9a871dbe050492c5faec865b620cd67 Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Wed, 4 Dec 2024 08:22:11 -0700 Subject: [PATCH 26/26] handle null result from fromJson Signed-off-by: Cody Cutrer --- .../openhab/binding/wiz/internal/utils/WizPacketConverter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java index 400745dd43b9b..bfe78eeabfeb1 100644 --- a/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java +++ b/bundles/org.openhab.binding.wiz/src/main/java/org/openhab/binding/wiz/internal/utils/WizPacketConverter.java @@ -82,6 +82,9 @@ public byte[] transformToByteMessage(final WizRequest requestPacket) { WizResponse response = null; try { response = this.wizGsonBuilder.fromJson(responseJson, WizResponse.class); + if (response == null) { + throw new JsonParseException("JSON is empty"); + } response.setWizResponseIpAddress(packet.getAddress().getHostAddress()); } catch (JsonParseException e) { logger.debug("Error parsing json! {}", e.getMessage());