Skip to content

Commit

Permalink
[gree] Minor improvements (openhab#8472)
Browse files Browse the repository at this point in the history
* Adding retries for status pool and api request
* README updated
* Implements openhab#8330: Swing Up/Down values 0-11
* Missing text resources added for V-SwingUpDown 7-11

Signed-off-by: Markus Michels <markus7017@gmail.com>
  • Loading branch information
markus7017 committed Sep 18, 2020
1 parent e9d7a88 commit abfaccf
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 66 deletions.
4 changes: 2 additions & 2 deletions bundles/org.openhab.binding.gree/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ No binding configuration is required.
| ipAddress | IP Address | IP address of the unit. |
| broadcastAddress | IP Address | Broadcast address being used for discovery, usually derived from the IP interface address. |
| refresh | Integer | Refresh interval in seconds for polling the device status. |
| currentTemperatureOffset | Decimal | The offset in Celsius for the current temperature value received from the device. |
| currentTemperatureOffset | Decimal | Offset in Celsius for the current temperature value received from the device. |

The Air Conditioner's IP address is mandatory, all other parameters are optional.
If the broadcast is not set (default) it will be derived from openHAB's network setting (PaperUI:Configuration:System:Network Settings).
Expand All @@ -41,7 +41,7 @@ The following channels are supported for fans:
| | | Mode can be one of auto/cool/eco/dry/fan/heat or on/off |
| | | Check the Air Conditioner's operating manual for supported modes. |
| temperature | Number:Temperature | Sets the desired room temperature. |
| currentTemperature | Number:Temperature | Displays the current room temperature. |
| currentTemperature | Number:Temperature | Displays the current room temperature (if supported by the unit, otherwise NaN). |
| air | Switch | Set on/off the Air Conditioner's Air function if applicable to the Air Conditioner model |
| dry | Switch | Set on/off the Air Conditioner's Dry function if applicable to the Air Conditioner model |
| health | Switch | Set on/off the Air Conditioner's Health function if applicable to the Air Conditioner model |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ public class GreeBindingConstants {
public static final int DISCOVERY_TIMEOUT_MS = 7000; // do not change!!
public static final int MAX_SCAN_CYCLES = 3;
public static final int REFRESH_INTERVAL_SEC = 5;
public static final int MAX_API_RETRIES = 3;

public static final int DIGITS_TEMP = 1;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,42 @@ public void setDeviceMode(DatagramSocket clientSocket, int value) throws GreeExc
setCommandValue(clientSocket, GREE_PROP_MODE, value);
}

/**
* SwUpDn: controls the swing mode of the vertical air blades
*
* 0: default
* 1: swing in full range
* 2: fixed in the upmost position (1/5)
* 3: fixed in the middle-up position (2/5)
* 4: fixed in the middle position (3/5)
* 5: fixed in the middle-low position (4/5)
* 6: fixed in the lowest position (5/5)
* 7: swing in the downmost region (5/5)
* 8: swing in the middle-low region (4/5)
* 9: swing in the middle region (3/5)
* 10: swing in the middle-up region (2/5)
* 11: swing in the upmost region (1/5)
*/
public void setDeviceSwingUpDown(DatagramSocket clientSocket, int value) throws GreeException {
// Only values 0,1,2,3,4,5,6,10,11 allowed
if ((value < 0 || value > 11) || (value > 6 && value < 10)) {
throw new GreeException("SwingUpDown value out of range!");
if (value < 0 || value > 11) {
throw new GreeException("SwingUpDown value is out of range!");
}
setCommandValue(clientSocket, GREE_PROP_SWINGUPDOWN, value);
}

/**
* SwingLfRig: controls the swing mode of the horizontal air blades (available on limited number of devices, e.g.
* some Cooper & Hunter units - thanks to mvmn)
*
* 0: default
* 1: full swing
* 2-6: fixed position from leftmost to rightmost
* Full swing, like for SwUpDn is not supported
*/
public void setDeviceSwingLeftRight(DatagramSocket clientSocket, int value) throws GreeException {
if (value < 0 || value > 6) {
throw new GreeException("SwingLeftRight value is out of range!");
}
setCommandValue(clientSocket, GREE_PROP_SWINGLEFTRIGHT, value, 0, 6);
}

Expand All @@ -224,6 +251,13 @@ public void setDeviceWindspeed(DatagramSocket clientSocket, int value) throws Gr
executeCommand(clientSocket, parameters);
}

/**
* Tur: sets fan speed to the maximum. Fan speed cannot be changed while active and only available in Dry and Cool
* mode.
*
* 0: off
* 1: on
*/
public void setDeviceTurbo(DatagramSocket clientSocket, int value) throws GreeException {
setCommandValue(clientSocket, GREE_PROP_TURBO, value, 0, 1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.RefreshType;
import org.eclipse.smarthome.core.types.State;
import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.gree.internal.GreeConfiguration;
import org.openhab.binding.gree.internal.GreeException;
import org.openhab.binding.gree.internal.GreeTranslationProvider;
Expand Down Expand Up @@ -70,6 +71,7 @@ public class GreeHandler extends BaseThingHandler {
private @Nullable ScheduledFuture<?> refreshTask;
private @Nullable Future<?> initializeFuture;
private long lastRefreshTime = 0;
private long apiRetries = 0;

public GreeHandler(Thing thing, GreeTranslationProvider messages, GreeDeviceFinder deviceFinder) {
super(thing);
Expand Down Expand Up @@ -138,62 +140,78 @@ public void handleCommand(ChannelUID channelUID, Command command) {
String channelId = channelUID.getIdWithoutGroup();
logger.debug("{}: Handle command {} for channel {}, command class {}", thingId, command, channelId,
command.getClass());
try {
DatagramSocket socket = clientSocket.get();
switch (channelId) {
case MODE_CHANNEL:
handleModeCommand(socket, command);
break;
case POWER_CHANNEL:
device.setDevicePower(socket, getOnOff(command));
break;
case TURBO_CHANNEL:
device.setDeviceTurbo(socket, getOnOff(command));
break;
case LIGHT_CHANNEL:
device.setDeviceLight(socket, getOnOff(command));
break;
case TARGET_TEMP_CHANNEL:
// Set value, read back effective one and update channel
// e.g. 22.5C will result in 22.0, because the AC doesn't support half-steps for C
device.setDeviceTempSet(socket, convertTemp(command));
break;
case SWINGUD_CHANNEL:
device.setDeviceSwingUpDown(socket, getNumber(command));
break;
case SWINGLR_CHANNEL:
device.setDeviceSwingLeftRight(socket, getNumber(command));
break;
case WINDSPEED_CHANNEL:
device.setDeviceWindspeed(socket, getNumber(command));
break;
case QUIET_CHANNEL:
handleQuietCommand(socket, command);
break;
case AIR_CHANNEL:
device.setDeviceAir(socket, getOnOff(command));
break;
case DRY_CHANNEL:
device.setDeviceDry(socket, getOnOff(command));
break;
case HEALTH_CHANNEL:
device.setDeviceHealth(socket, getOnOff(command));
break;
case PWRSAV_CHANNEL:
device.setDevicePwrSaving(socket, getOnOff(command));
break;

int retries = MAX_API_RETRIES;
do {
try {
sendRequest(channelId, command);
// force refresh on next status refresh cycle
forceRefresh = true;
apiRetries = 0;
} catch (GreeException e) {
retries--;
if (retries > 0) {
logger.debug("{}: Command {} failed for channel {}, retry", thingId, command, channelId);
} else {
String message = logInfo(
messages.get("command.exception", command, channelId) + ": " + e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
}
} catch (IllegalArgumentException e) {
logInfo("command.invarg", command, channelId);
retries = 0;
} catch (RuntimeException e) {
logger.warn("{}: {}", thingId, messages.get("command.exception", command, channelId), e);
retries = 0;
}
} while (retries > 0);
}
}

// force refresh on next status refresh cycle
forceRefresh = true;
} catch (GreeException e) {
String message = logInfo("command.exception", command, channelId) + ": " + e.getMessage();
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
} catch (IllegalArgumentException e) {
logInfo("command.invarg", command, channelId);
} catch (RuntimeException e) {
logger.warn("{}: {}", thingId, messages.get("command.exception", command, channelId), e);
}
private void sendRequest(String channelId, Command command) throws GreeException {
DatagramSocket socket = clientSocket.get();
switch (channelId) {
case MODE_CHANNEL:
handleModeCommand(socket, command);
break;
case POWER_CHANNEL:
device.setDevicePower(socket, getOnOff(command));
break;
case TURBO_CHANNEL:
device.setDeviceTurbo(socket, getOnOff(command));
break;
case LIGHT_CHANNEL:
device.setDeviceLight(socket, getOnOff(command));
break;
case TARGET_TEMP_CHANNEL:
// Set value, read back effective one and update channel
// e.g. 22.5C will result in 22.0, because the AC doesn't support half-steps for C
device.setDeviceTempSet(socket, convertTemp(command));
break;
case SWINGUD_CHANNEL:
device.setDeviceSwingUpDown(socket, getNumber(command));
break;
case SWINGLR_CHANNEL:
device.setDeviceSwingLeftRight(socket, getNumber(command));
break;
case WINDSPEED_CHANNEL:
device.setDeviceWindspeed(socket, getNumber(command));
break;
case QUIET_CHANNEL:
handleQuietCommand(socket, command);
break;
case AIR_CHANNEL:
device.setDeviceAir(socket, getOnOff(command));
break;
case DRY_CHANNEL:
device.setDeviceDry(socket, getOnOff(command));
break;
case HEALTH_CHANNEL:
device.setDeviceHealth(socket, getOnOff(command));
break;
case PWRSAV_CHANNEL:
device.setDevicePwrSaving(socket, getOnOff(command));
break;
}
}

Expand Down Expand Up @@ -336,12 +354,15 @@ private void startAutomaticRefresh() {
// Get the current status from the Airconditioner

if (getThing().getStatus() == ThingStatus.OFFLINE) {
// try to re-initialize thing access
logger.debug("{}: Re-initialize device", thingId);
initializeThing();
return;
}

if (clientSocket.isPresent()) {
device.getDeviceStatus(clientSocket.get());
apiRetries = 0; // the call was successful without an exception
logger.debug("{}: Executing automatic update of values", thingId);
List<Channel> channels = getThing().getChannels();
for (Channel channel : channels) {
Expand All @@ -363,11 +384,16 @@ private void startAutomaticRefresh() {
} else {
logger.debug("{}: {}", thingId, message);
}
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);

apiRetries++;
if (apiRetries > MAX_API_RETRIES) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message);
}
}
} catch (RuntimeException e) {
String message = messages.get("update.exception", "RuntimeException");
logger.warn("{}: {}", thingId, message, e);
apiRetries++;
}
};

Expand Down Expand Up @@ -519,8 +545,11 @@ private void publishChannel(ChannelUID channelUID) {

private @Nullable State updateCurrentTemp() throws GreeException {
if (device.hasStatusValChanged(GREE_PROP_CURRENT_TEMP_SENSOR)) {
return new DecimalType(device.getIntStatusVal(GREE_PROP_CURRENT_TEMP_SENSOR) + INTERNAL_TEMP_SENSOR_OFFSET
+ config.currentTemperatureOffset.doubleValue());
double temp = device.getIntStatusVal(GREE_PROP_CURRENT_TEMP_SENSOR);
return temp != 0
? new DecimalType(
temp + INTERNAL_TEMP_SENSOR_OFFSET + config.currentTemperatureOffset.doubleValue())
: UnDefType.UNDEF;
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ channel-type.gree.swingupdown.option.3 = Mid-Up
channel-type.gree.swingupdown.option.4 = Mid
channel-type.gree.swingupdown.option.5 = Mid-Down
channel-type.gree.swingupdown.option.6 = Down
channel-type.gree.swingupdown.option.7 = Swing Downmost
channel-type.gree.swingupdown.option.8 = Swing Middle-Low
channel-type.gree.swingupdown.option.9 = Swing Middle
channel-type.gree.swingupdown.option.10 = Swing Middle-Up
channel-type.gree.swingupdown.option.11 = Swing Upmost
channel-type.gree.swingleftright.label = Horizontal Swing Mode
channel-type.gree.swingleftright.description = Sets the horizontal swing action on the Air Conditioner: 0=OFF, 1=Full Swing, 2=Left, 3=Mid-Left, 4=Mid, 5=Mid-Right, 6=Right
channel-type.gree.swingleftright.option.0 = OFF
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,22 @@ channel-type.gree.quiet.description = Leisemodus w
channel-type.gree.quiet.state.option.off = Aus
channel-type.gree.quiet.state.option.auto = Auto
channel-type.gree.quiet.state.option.quiet = Leise
channel-type.gree.swingupdown.label = Lamellenmodus
channel-type.gree.swingupdown.description = Auswahl des Lamellenmodus: 0=Aus, 1=Voller Flügel, 2=Hoch, 3=Mittelhoch, 3=Mitte, 5=Mitteltief, 6=Tief. Verfügbarkeit ist abhängig vom Gerätemodell.
channel-type.gree.swingupdown.label = V-Lamellenmodus
channel-type.gree.swingupdown.description = Auswahl des vertikalen Lamellenmodus: 0=Aus, 1=Voller Flügel, 2=Hoch, 3=Mittelhoch, 3=Mitte, 5=Mitteltief, 6=Tief. Verfügbarkeit ist abhängig vom Gerätemodell.
channel-type.gree.swingupdown.option.0 = Aus
channel-type.gree.swingupdown.option.1 = Voller Flügel
channel-type.gree.swingupdown.option.2 = Hoch
channel-type.gree.swingupdown.option.3 = Mittelhoch
channel-type.gree.swingupdown.option.4 = Mitte
channel-type.gree.swingupdown.option.5 = Mitteltief
channel-type.gree.swingupdown.option.6 = Tief
channel-type.gree.swingleftright.label = Lamellenmodus
channel-type.gree.swingleftright.description = Auswahl des Lamellenmodus: 0=Aus, 1=Voller Flügel, 2=Links, 3=Mitte-Links, 4=Mitte, 5=Mitte-Rechts, 6=Rechts. Verfügbarkeit ist abhängig vom Gerätemodell.
channel-type.gree.swingupdown.option.7 = Unterre Region
channel-type.gree.swingupdown.option.8 = Mittlere Region
channel-type.gree.swingupdown.option.9 = Region Mitte-unten
channel-type.gree.swingupdown.option.10 = Region Mitte-oben
channel-type.gree.swingupdown.option.11 = Obere Region
channel-type.gree.swingleftright.label = H-Lamellenmodus
channel-type.gree.swingleftright.description = Auswahl des horizontalen Lamellenmodus: 0=Aus, 1=Voller Flügel, 2=Links, 3=Mitte-Links, 4=Mitte, 5=Mitte-Rechts, 6=Rechts. Verfügbarkeit ist abhängig vom Gerätemodell.
channel-type.gree.swingleftright.option.0 = AUS
channel-type.gree.swingleftright.option.1 = Voller Flügel
channel-type.gree.swingleftright.option.2 = Links
Expand Down

0 comments on commit abfaccf

Please sign in to comment.