Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mideaac] Initial contribution- second try #17749

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,11 @@
<artifactId>org.openhab.binding.mffan</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.mideaac</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.miele</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.mideaac/NOTICE
Original file line number Diff line number Diff line change
@@ -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
120 changes: 120 additions & 0 deletions bundles/org.openhab.binding.mideaac/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Midea AC Binding

This binding integrates Air Conditioners that use the Midea protocol. Midea is an OEM for many brands.

An AC device is likely supported if it uses one of the following Android apps or it's iOS equivalent.

| Application | Comment | Options |
|--:-------------------------------------------|--:------------------------------------|--------------|
| Midea Air (com.midea.aircondition.obm) | Full Support of key and token updates | Midea Air |
| NetHome Plus (com.midea.aircondition) | Full Support of key and token updates | NetHome Plus |
| SmartHome/MSmartHome (com.midea.ai.overseas) | Full Support of key and token updates | MSmartHome |

Note: The Air Conditioner must already be set-up on the WiFi network and have a fixed IP Address with one of the three apps listed above for full discovery and key and token updates.

## Supported Things

This binding supports one Thing type `ac`.

## Discovery

Once the Air Conditioner is on the network (WiFi active) the other required parameters can be discovered automatically.
An IP broadcast message is sent and every responding unit gets added to the Inbox.
As an alternative use the python application msmart-ng from <https://github.com/mill1000/midea-msmart> with the msmart-ng discover ipAddress option.

## Binding Configuration

No binding configuration is required.

## Thing Configuration

| Parameter | Required ? | Comment | Default |
|--:----------|--:----------|--:----------------------------------------------------------------|---------|
| ipAddress | Yes | IP Address of the device. | |
| ipPort | Yes | IP port of the device | 6444 |
| deviceId | Yes | ID of the device. Leave 0 to do ID discovery (length 6 bytes). | 0 |
| cloud | Yes for V.3 | Cloud Provider name for email and password | |
| email | No | Email for cloud account chosen in Cloud Provider. | |
| password | No | Password for cloud account chosen in Cloud Provider. | |
| token | Yes for V.3 | Secret Token (length 128 HEX) | |
| key | Yes for V.3 | Secret Key (length 64 HEX) | |
| pollingTime | Yes | Polling time in seconds. Minimum time is 30 seconds. | 60 |
| timeout | Yes | Connecting timeout. Minimum time is 2 second, maximum 10 seconds. | 4 |
| promptTone | Yes | "Ding" tone when command is received and executed. | False |
| version | Yes | Version 3 has token, key and cloud requirements. | 0 |

## Channels

Following channels are available:

| Channel | Type | Description | Read only | Advanced |
|--:---------------------------|--:-----------------|--:-----------------------------------------------------------------------------------------------------|--:--------|--:-------|
| power | Switch | Turn the AC on and off. | | |
| target-temperature | Number:Temperature | Target temperature. | | |
| operational-mode | String | Operational mode: OFF (turns off), AUTO, COOL, DRY, HEAT, FAN ONLY | | |
| fan-speed | String | Fan speed: OFF (turns off), SILENT, LOW, MEDIUM, HIGH, AUTO. Not all modes supported by all units. | | |
| swing-mode | String | Swing mode: OFF, VERTICAL, HORIZONTAL, BOTH. Not all modes supported by all units. | | |
| eco-mode | Switch | Eco mode - Cool only (Temperature is set to 24 C (75 F) and fan on AUTO) | | |
| turbo-mode | Switch | Turbo mode, "Boost" in Midea Air app, long press "+" on IR Remote Controller. COOL and HEAT mode only. | | |
| sleep-function | Switch | Sleep function ("Moon with a star" icon on IR Remote Controller). | | |
| indoor-temperature | Number:Temperature | Indoor temperature measured in the room, where internal unit is installed. | Yes | |
| outdoor-temperature | Number:Temperature | Outdoor temperature by external unit. Some units do not report reading when off. | Yes | |
| temperature-unit | Switch | Sets the LED display on the evaporator to Fahrenheit (true) or Celsius (false). | | Yes |
| on-timer | String | Sets the future time to turn on the AC. | | Yes |
| off-timer | String | Sets the future time to turn off the AC. | | Yes |
| screen-display | Switch | If device supports across LAN, turns off the LED display. | | Yes |
| humidity | Number | If device supports, the indoor humidity. | Yes | Yes |
| appliance-error | Switch | If device supports, appliance error | Yes | Yes |
| auxiliary-heat | Switch | If device supports, auxiliary heat | Yes | Yes |
| alternate-target-temperature | Number:Temperature | Alternate Target Temperature - not currently used | Yes | Yes |

## Examples

### `demo.things` Example

```java
Thing mideaac:ac:mideaac "myAC" @ "Room" [ ipAddress="192.168.1.200", ipPort="6444", deviceId="deviceId", cloud="your cloud (e.g NetHome Plus)", email="[email protected]", password="yourcloudpassword", token="token", key ="key", pollingTime = 60, timeout=4, promptTone="false", version="3"]
```

Option to use the built-in binding discovery of ipPort, deviceId, token and key.

```java
Thing mideaac:ac:mideaac "myAC" @ "Room" [ ipAddress="192.168.1.200", ipPort="", deviceId="", cloud="your cloud (e.g NetHome Plus)", email="[email protected]", password="yourcloudpassword", token="", key ="", pollingTime = 60, timeout=4, promptTone="false", version="3"]
```

### `demo.items` Example

```java
Switch power "Power" { channel="mideaac:ac:mideaac:power" }
Number:Temperature target_temperature "Target Temperature [%.1f °F]" { channel="mideaac:ac:mideaac:target-temperature" }
String operational_mode "Operational Mode" { channel="mideaac:ac:mideaac:operational-mode" }
String fan_speed "Fan Speed" { channel="mideaac:ac:mideaac:fan-speed" }
String swing_mode "Swing Mode" { channel="mideaac:ac:mideaac:swing-mode" }
Number:Temperature indoor_temperature "Indoor Temperature [%.1f °F]" { channel="mideaac:ac:mideaac:indoor-temperature" }
Number:Temperature outdoor_temperature "Current Temperature [%.1f °F]" { channel="mideaac:ac:mideaac:outdoor-temperature" }
Switch eco_mode "Eco Mode" { channel="mideaac:ac:mideaac:eco-mode" }
Switch turbo_mode "Turbo Mode" { channel="mideaac:ac:mideaac:turbo-mode" }
Switch sleep_function "Sleep function" { channel="mideaac:ac:mideaac:sleep-function" }
Switch temperature_unit "Fahrenheit or Celsius" { channel="mideaac:ac:mideaac:temperature-unit" }
```

### `demo.sitemap` Example

```java
sitemap midea label="Split AC MBR"{
Frame label="AC Unit" {
Text item=outdoor_temperature label="Outdoor Temperature [%.1f °F]"
Text item=indoor_temperature label="Indoor Temperature [%.1f °F]"
Setpoint item=target_temperature label="Target Temperature [%.1f °F]" minValue=63.0 maxValue=78 step=1.0
Switch item=power label="Midea AC Power"
Switch item=temperature_unit label= "Temp Unit" mappings=[ON="Fahrenheit", OFF="Celsius"]
Selection item=fan_speed label="Midea AC Fan Speed"
Selection item=operational_mode label="Midea AC Mode"
Selection item=swing_mode label="Midea AC Louver Swing Mode"
}
}
```

## Debugging and Tracing

Switch the log level to TRACE or DEBUG on the UI Settings Page (Add-on Settings)
17 changes: 17 additions & 0 deletions bundles/org.openhab.binding.mideaac/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>4.3.0-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.binding.mideaac</artifactId>

<name>openHAB Add-ons :: Bundles :: MideaAC Binding</name>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.mideaac-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>

<feature name="openhab-binding-mideaac" description="MideaAC Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.mideaac/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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.mideaac.internal;

import java.util.Collections;
import java.util.Set;

import javax.measure.Unit;
import javax.measure.quantity.Temperature;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.thing.ThingTypeUID;

/**
* The {@link MideaACBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Jacek Dobrowolski - Initial contribution
* @author Bob Eckhoff - OH naming conventions
*/
@NonNullByDefault
public class MideaACBindingConstants {

private static final String BINDING_ID = "mideaac";

/**
* Thing Type
*/
public static final ThingTypeUID THING_TYPE_MIDEAAC = new ThingTypeUID(BINDING_ID, "ac");

public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_MIDEAAC);

/**
* List of all channel IDS
*/
public static final String CHANNEL_POWER = "power";
public static final String CHANNEL_APPLIANCE_ERROR = "appliance-error";
public static final String CHANNEL_TARGET_TEMPERATURE = "target-temperature";
public static final String CHANNEL_OPERATIONAL_MODE = "operational-mode";
public static final String CHANNEL_FAN_SPEED = "fan-speed";
public static final String CHANNEL_ON_TIMER = "on-timer";
public static final String CHANNEL_OFF_TIMER = "off-timer";
public static final String CHANNEL_SWING_MODE = "swing-mode";
public static final String CHANNEL_AUXILIARY_HEAT = "auxiliary-heat";
public static final String CHANNEL_ECO_MODE = "eco-mode";
public static final String CHANNEL_TEMPERATURE_UNIT = "temperature-unit";
public static final String CHANNEL_SLEEP_FUNCTION = "sleep-function";
public static final String CHANNEL_TURBO_MODE = "turbo-mode";
public static final String CHANNEL_INDOOR_TEMPERATURE = "indoor-temperature";
public static final String CHANNEL_OUTDOOR_TEMPERATURE = "outdoor-temperature";
public static final String CHANNEL_HUMIDITY = "humidity";
public static final String CHANNEL_ALTERNATE_TARGET_TEMPERATURE = "alternate-target-temperature";
public static final String CHANNEL_SCREEN_DISPLAY = "screen-display";
public static final String DROPPED_COMMANDS = "dropped-commands";

public static final Unit<Temperature> API_TEMPERATURE_UNIT = SIUnits.CELSIUS;

/**
* Commands sent to/from AC wall unit are ASCII
*/
public static final String CHARSET = "US-ASCII";

/**
* List of all AC thing properties
*/
public static final String CONFIG_IP_ADDRESS = "ipAddress";
public static final String CONFIG_IP_PORT = "ipPort";
public static final String CONFIG_DEVICEID = "deviceId";
public static final String CONFIG_CLOUD = "cloud";
public static final String CONFIG_EMAIL = "email";
public static final String CONFIG_PASSWORD = "password";
public static final String CONFIG_TOKEN = "token";
public static final String CONFIG_KEY = "key";
public static final String CONFIG_POLLING_TIME = "pollingTime";
public static final String CONFIG_CONNECTING_TIMEOUT = "timeout";
public static final String CONFIG_PROMPT_TONE = "promptTone";
public static final String CONFIG_VERSION = "version";

public static final String PROPERTY_SN = "sn";
public static final String PROPERTY_SSID = "ssid";
public static final String PROPERTY_TYPE = "type";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/**
* 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.mideaac.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link MideaACConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Jacek Dobrowolski - Initial contribution
* @author Bob Eckhoff - OH addons changes
*/
@NonNullByDefault
public class MideaACConfiguration {

/**
* IP Address
*/
public String ipAddress = "";

/**
* IP Port
*/
public int ipPort = 6444;

/**
* Device ID
*/
public String deviceId = "0";

/**
* Cloud Account email
*/
public String email = "";

/**
* Cloud Account Password
*/
public String password = "";

/**
* Cloud Provider
*/
public String cloud = "";

/**
* Token
*/
public String token = "";

/**
* Key
*/
public String key = "";

/**
* Poll Frequency
*/
public int pollingTime = 60;

/**
* Socket Timeout
*/
public int timeout = 4;

/**
* Prompt tone from indoor unit with a Set Command
*/
public boolean promptTone = false;

/**
* AC Version
*/
public int version = 0;

/**
* Check during initialization that the params are valid
*
* @return true(valid), false (not valid)
*/
public boolean isValid() {
return !("0".equalsIgnoreCase(deviceId) || deviceId.isBlank() || ipPort <= 0 || ipAddress.isBlank()
|| version <= 1);
}

/**
* Check during initialization if discovery is needed
*
* @return true(discovery needed), false (not needed)
*/
public boolean isDiscoveryNeeded() {
return ("0".equalsIgnoreCase(deviceId) || deviceId.isBlank() || ipPort <= 0 || ipAddress.isBlank()
|| !Utils.validateIP(ipAddress) || version <= 1);
}

/**
* Check during initialization if key and token can be obtained
* from the cloud.
*
* @return true (yes they can), false (they cannot)
*/
public boolean isTokenKeyObtainable() {
return (!email.isBlank() && !password.isBlank() && !"".equals(cloud));
}

/**
* Check during initialization if cloud, key and token are true for v3
*
* @return true (Valid, all items are present) false (key, token and/or provider missing)
*/
public boolean isV3ConfigValid() {
return (!key.isBlank() && !token.isBlank() && !"".equals(cloud));
}
}
Loading