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

[MyQ] Initial commit of the MyQ binding for OH3 #9347

Merged
merged 6 commits into from
Feb 26, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
/bundles/org.openhab.binding.mqtt.generic/ @davidgraeff
/bundles/org.openhab.binding.mqtt.homeassistant/ @davidgraeff
/bundles/org.openhab.binding.mqtt.homie/ @davidgraeff
/bundles/org.openhab.binding.myq/ @digitaldan
/bundles/org.openhab.binding.mystrom/ @pail23
/bundles/org.openhab.binding.nanoleaf/ @raepple
/bundles/org.openhab.binding.neato/ @jjlauterbach
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.myq/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
68 changes: 68 additions & 0 deletions bundles/org.openhab.binding.myq/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# MyQ Binding

This binding integrates with the [The Chamberlain Group MyQ](https://www.myq.com) cloud service. It allows monitoring and control over [MyQ](https://www.myq.com) enabled garage doors manufactured by LiftMaster, Chamberlain and Craftsman.

## Supported Things

### Account

This represents the MyQ cloud account and uses the same credentials needed when using the MyQ mobile application.

ThingTypeUID: `account`

### Garage Door

This represents a garage door associated with an account. Multiple garage doors are supported.

ThingTypeUID: `garagedoor`

### Lamp

This represents a lamp associated with an account. Multiple lamps are supported.

ThingTypeUID: `lamp`

## Discovery

Once an account has been added, garage doors and lamps will automatically be discovered and added to the inbox.

## Channels

| Channel | Item Type | Thing Type | States |
|---------------|---------------|------------------|--------------------------------------------------------|
| status | String | garagedoor | opening, closed, closing, stopped, transition, unknown |
| rollershutter | Rollershutter | garagedoor | UP, DOWN, 0%, 100% |
| switch | Switch | garagedoor, lamp | ON (open), OFF (closed)

## Full Example

### Thing Configuration

```xtend
Bridge myq:account:home "MyQ Account" [ username="foo@bar.com", password="secret", refreshInterval=60 ] {
Thing garagedoor abcd12345 "MyQ Garage Door" [ serialNumber="abcd12345" ]
Thing lamp efgh6789 "MyQ Lamp" [ serialNumber="efgh6789" ]
}
```

### Items

```xtend
String MyQGarageDoor1Status "Door Status [%s]" {channel = "myq:garagedoor:home:abcd12345:status"}
Switch MyQGarageDoor1Switch "Door Switch [%s]" {channel = "myq:garagedoor:home:abcd12345:switch"}
Rollershutter MyQGarageDoor1Rollershutter "Door Rollershutter [%s]" {channel = "myq:garagedoor:home:abcd12345:rollershutter"}
Switch MyQGarageDoorLamp "Lamp [%s]" {channel = "myq:lamp:home:efgh6789:switch"}
}
```

### Sitemaps

```xtend
sitemap MyQ label="MyQ Demo Sitemap" {
Frame label="Garage Door" {
String item=MyQGarageDoor1Status
Switch item=MyQGarageDoor1Switch
Rollershutter item=MyQGarageDoor1Rollershutter
}
}
```
17 changes: 17 additions & 0 deletions bundles/org.openhab.binding.myq/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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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>3.1.0-SNAPSHOT</version>
</parent>

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

<name>openHAB Add-ons :: Bundles :: MyQ 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.myq-${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-myq" description="MyQ Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.myq/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010-2021 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.myq.internal;

import java.util.Set;

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

/**
* The {@link MyQBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Dan Cunningham - Initial contribution
*/
@NonNullByDefault
public class MyQBindingConstants {

public static final String BINDING_ID = "myq";

public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account");
public static final ThingTypeUID THING_TYPE_GARAGEDOOR = new ThingTypeUID(BINDING_ID, "garagedoor");
public static final ThingTypeUID THING_TYPE_LAMP = new ThingTypeUID(BINDING_ID, "lamp");
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT, THING_TYPE_GARAGEDOOR,
THING_TYPE_LAMP);
public static final Set<ThingTypeUID> SUPPORTED_DISCOVERY_THING_TYPES_UIDS = Set.of(THING_TYPE_GARAGEDOOR,
THING_TYPE_LAMP);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Copyright (c) 2010-2021 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.myq.internal;

import static org.openhab.binding.myq.internal.MyQBindingConstants.BINDING_ID;

import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.myq.internal.dto.DevicesDTO;
import org.openhab.binding.myq.internal.handler.MyQAccountHandler;
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.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerService;

/**
* The {@link MyQDiscoveryService} is responsible for discovering MyQ things
*
* @author Dan Cunningham - Initial contribution
*/
@NonNullByDefault
public class MyQDiscoveryService extends AbstractDiscoveryService implements DiscoveryService, ThingHandlerService {
public MyQDiscoveryService() throws IllegalArgumentException {
digitaldan marked this conversation as resolved.
Show resolved Hide resolved
super(SUPPORTED_DISCOVERY_THING_TYPES_UIDS, 1, true);
}

private static final Set<ThingTypeUID> SUPPORTED_DISCOVERY_THING_TYPES_UIDS = Set
.of(MyQBindingConstants.THING_TYPE_GARAGEDOOR, MyQBindingConstants.THING_TYPE_LAMP);

private @Nullable MyQAccountHandler accountHandler;
digitaldan marked this conversation as resolved.
Show resolved Hide resolved

@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
return SUPPORTED_DISCOVERY_THING_TYPES_UIDS;
}

@Override
public void startScan() {
MyQAccountHandler accountHandler = this.accountHandler;
if (accountHandler != null) {
DevicesDTO devices = accountHandler.devicesCache();
if (devices != null) {
devices.items.forEach(device -> {
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily);
if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) {
ThingUID thingUID = new ThingUID(thingTypeUID, accountHandler.getThing().getUID(),
device.serialNumber.toLowerCase());
DiscoveryResult result = DiscoveryResultBuilder.create(thingUID).withLabel("MyQ " + device.name)
.withProperty("serialNumber", thingUID.getId())
digitaldan marked this conversation as resolved.
Show resolved Hide resolved
.withRepresentationProperty("serialNumber")
.withBridge(accountHandler.getThing().getUID()).build();
thingDiscovered(result);
}
});
}
}
}

@Override
public void setThingHandler(ThingHandler handler) {
if (handler instanceof MyQAccountHandler) {
accountHandler = (MyQAccountHandler) handler;
}
}

@Override
public @Nullable ThingHandler getThingHandler() {
return accountHandler;
}

@Override
public void activate() {
super.activate(null);
}

@Override
public void deactivate() {
super.deactivate();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* Copyright (c) 2010-2021 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.myq.internal;

import static org.openhab.binding.myq.internal.MyQBindingConstants.*;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.myq.internal.handler.MyQAccountHandler;
import org.openhab.binding.myq.internal.handler.MyQGarageDoorHandler;
import org.openhab.binding.myq.internal.handler.MyQLampHandler;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Bridge;
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;

/**
* The {@link MyQHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Dan Cunningham - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.myq", service = ThingHandlerFactory.class)
public class MyQHandlerFactory extends BaseThingHandlerFactory {
private final HttpClient httpClient;

@Activate
public MyQHandlerFactory(final @Reference HttpClientFactory httpClientFactory) {
this.httpClient = httpClientFactory.getCommonHttpClient();
}

@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}

@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();

if (THING_TYPE_ACCOUNT.equals(thingTypeUID)) {
return new MyQAccountHandler((Bridge) thing, httpClient);
}

if (THING_TYPE_GARAGEDOOR.equals(thingTypeUID)) {
return new MyQGarageDoorHandler(thing);
}

if (THING_TYPE_LAMP.equals(thingTypeUID)) {
return new MyQLampHandler(thing);
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.config;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link MyQAccountConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Dan Cunningham - Initial contribution
*/
@NonNullByDefault
public class MyQAccountConfiguration {
public String username = "";
public String password = "";
public Integer refreshInterval = 60;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.config;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link MyQDeviceConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Dan Cunningham - Initial contribution
*/
@NonNullByDefault
public class MyQDeviceConfiguration {
public String serialNumber = "";
}
Loading