[generacmobilelink| Initial Contribution (#9322)
* This is the initial contribution of the Generac MobileLink binding. This allows the Generac line of generators using their MobileLink cloud service to be monitored as things in openHAB. * bump to 3.1 Signed-off-by: Dan Cunningham <dan@digitaldan.com>
This commit is contained in:
parent
03dd4d491f
commit
6cb9f3a93e
|
@ -80,6 +80,7 @@
|
||||||
/bundles/org.openhab.binding.ftpupload/ @paulianttila
|
/bundles/org.openhab.binding.ftpupload/ @paulianttila
|
||||||
/bundles/org.openhab.binding.gardena/ @gerrieg
|
/bundles/org.openhab.binding.gardena/ @gerrieg
|
||||||
/bundles/org.openhab.binding.gce/ @clinique
|
/bundles/org.openhab.binding.gce/ @clinique
|
||||||
|
/bundles/org.openhab.binding.generacmobilelink/ @digitaldan
|
||||||
/bundles/org.openhab.binding.globalcache/ @mhilbush
|
/bundles/org.openhab.binding.globalcache/ @mhilbush
|
||||||
/bundles/org.openhab.binding.goecharger/ @SamuelBrucksch
|
/bundles/org.openhab.binding.goecharger/ @SamuelBrucksch
|
||||||
/bundles/org.openhab.binding.gpstracker/ @gbicskei
|
/bundles/org.openhab.binding.gpstracker/ @gbicskei
|
||||||
|
|
|
@ -386,6 +386,11 @@
|
||||||
<artifactId>org.openhab.binding.gce</artifactId>
|
<artifactId>org.openhab.binding.gce</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
|
<artifactId>org.openhab.binding.generacmobilelink</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openhab.addons.bundles</groupId>
|
<groupId>org.openhab.addons.bundles</groupId>
|
||||||
<artifactId>org.openhab.binding.globalcache</artifactId>
|
<artifactId>org.openhab.binding.globalcache</artifactId>
|
||||||
|
|
|
@ -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
|
|
@ -0,0 +1,95 @@
|
||||||
|
# Generac MobileLink Binding
|
||||||
|
|
||||||
|
This binding communicates with the Generac MobileLink API and reports on the status of Generac manufactured generators, including versions resold under the brands Eaton, Honeywell and Siemens.
|
||||||
|
|
||||||
|
## Supported Things
|
||||||
|
|
||||||
|
|
||||||
|
### MobileLink Account
|
||||||
|
|
||||||
|
A MobileLink account bridge thing represents a user's MobileLink account and is responsible for authentication and polling for updates.
|
||||||
|
|
||||||
|
ThingTypeUID: `account`
|
||||||
|
|
||||||
|
### Generator
|
||||||
|
|
||||||
|
A Generator thing represents a individual generator linked to an account bridge. Multiple generators are supported.
|
||||||
|
|
||||||
|
ThingTypeUID: `generator`
|
||||||
|
|
||||||
|
## Discovery
|
||||||
|
|
||||||
|
The MobileLink account bridge must be added manually. Once added, generator things will automatically be added to the inbox.
|
||||||
|
|
||||||
|
## Thing Configuration
|
||||||
|
|
||||||
|
### MobileLink Account
|
||||||
|
|
||||||
|
| Parameter | Description |
|
||||||
|
|-----------------|------------------------------------------------------------------------------------|
|
||||||
|
| username | The user name, typically an email address, used to login to the MobileLink service |
|
||||||
|
| password | The password used to login to the MobileLink service |
|
||||||
|
| refreshInterval | The frequency to poll for generator updates, minimum duration is 30 seconds |
|
||||||
|
|
||||||
|
|
||||||
|
## Channels
|
||||||
|
|
||||||
|
### Generator Channels
|
||||||
|
|
||||||
|
All channels are read-only.
|
||||||
|
|
||||||
|
| channel | type | description |
|
||||||
|
|-------------------------|----------------------|-------------------------------------------|
|
||||||
|
| connected | Switch | Connected status |
|
||||||
|
| greenLight | Switch | Green light state (typically auto mode) |
|
||||||
|
| yellowLight | Switch | Yellow light state |
|
||||||
|
| redLight | Switch | Red light state (typically off mode) |
|
||||||
|
| blueLight | Switch | Blue light state (typically running mode) |
|
||||||
|
| statusDate | DateTime | Status date (start of day) |
|
||||||
|
| status | String | General status |
|
||||||
|
| currentAlarmDescription | String | Current alarm description |
|
||||||
|
| runHours | Number:Time | Number of run hours |
|
||||||
|
| exerciseHours | Number:Time | Number of exercise hours |
|
||||||
|
| fuelType | Number | Fuel type |
|
||||||
|
| fuelLevel | Number:Dimensionless | Fuel level |
|
||||||
|
| batteryVoltage | String | Battery voltage status |
|
||||||
|
| serviceStatus | Switch | Service status |
|
||||||
|
|
||||||
|
|
||||||
|
## Full Example
|
||||||
|
|
||||||
|
### Things
|
||||||
|
|
||||||
|
```xtend
|
||||||
|
Bridge generacmobilelink:account:main "MobileLink Account" [ userName="foo@bar.com", password="secret",refreshInterval=60 ] {
|
||||||
|
Thing generator 123456 "MobileLink Generator" [ generatorId="123456" ]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Items
|
||||||
|
|
||||||
|
```xtend
|
||||||
|
Switch GeneratorConnected "Connected [%s]" {channel="generacmobilelink:generator:main:123456:connected"}
|
||||||
|
Switch GeneratorGreenLight "Green Light [%s]" {channel="generacmobilelink:generator:main:123456:greenLight"}
|
||||||
|
Switch GeneratorYellowLight "Yellow Light [%s]" {channel="generacmobilelink:generator:main:123456:yellowLight"}
|
||||||
|
Switch GeneratorBlueLight "Blue Light [%s]" {channel="generacmobilelink:generator:main:123456:blueLight"}
|
||||||
|
Switch GeneratorRedLight "Red Light [%s]" {channel="generacmobilelink:generator:main:123456:redLight"}
|
||||||
|
String GeneratorStatus "Status [%s]" {channel="generacmobilelink:generator:main:123456:status"}
|
||||||
|
String GeneratorAlarm "Alarm [%s]" {channel="generacmobilelink:generator:main:123456:currentAlarmDescription"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sitemap
|
||||||
|
|
||||||
|
```xtend
|
||||||
|
sitemap MobileLink label="Demo Sitemap" {
|
||||||
|
Frame label="Generator" {
|
||||||
|
Switch item=GeneratorConnected
|
||||||
|
Switch item=GeneratorGreenLight
|
||||||
|
Switch item=GeneratorYellowLight
|
||||||
|
Switch item=GeneratorBlueLight
|
||||||
|
Switch item=GeneratorRedLight
|
||||||
|
Text item=GeneratorStatus
|
||||||
|
Text item=GeneratorAlarm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -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.generacmobilelink</artifactId>
|
||||||
|
|
||||||
|
<name>openHAB Add-ons :: Bundles :: GeneracMobileLink Binding</name>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
-->
|
||||||
|
<features name="org.openhab.binding.generacmobilelink-${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-generacmobilelink" description="Generac MobileLink Binding" version="${project.version}">
|
||||||
|
<feature>openhab-runtime-base</feature>
|
||||||
|
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.generacmobilelink/${project.version}</bundle>
|
||||||
|
</feature>
|
||||||
|
</features>
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GeneracMobileLinkBindingConstants} class defines common constants, which are
|
||||||
|
* used across the whole binding.
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class GeneracMobileLinkBindingConstants {
|
||||||
|
private static final String BINDING_ID = "generacmobilelink";
|
||||||
|
public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account");
|
||||||
|
public static final ThingTypeUID THING_TYPE_GENERATOR = new ThingTypeUID(BINDING_ID, "generator");
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.config;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GeneracMobileLinkAccountConfiguration} class contains fields mapping thing configuration parameters.
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class GeneracMobileLinkAccountConfiguration {
|
||||||
|
public String username = "";
|
||||||
|
public String password = "";
|
||||||
|
public Integer refreshInterval = 60;
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.discovery;
|
||||||
|
|
||||||
|
import static org.openhab.binding.generacmobilelink.internal.GeneracMobileLinkBindingConstants.THING_TYPE_GENERATOR;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.GeneracMobileLinkBindingConstants;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.GeneratorStatusDTO;
|
||||||
|
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||||
|
import org.openhab.core.thing.ThingTypeUID;
|
||||||
|
import org.openhab.core.thing.ThingUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GeneracMobileLinkDiscoveryService} is responsible for discovering generator things
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class GeneracMobileLinkDiscoveryService extends AbstractDiscoveryService {
|
||||||
|
private static final Set<ThingTypeUID> SUPPORTED_DISCOVERY_THING_TYPES_UIDS = Set.of(THING_TYPE_GENERATOR);
|
||||||
|
|
||||||
|
public GeneracMobileLinkDiscoveryService() {
|
||||||
|
super(SUPPORTED_DISCOVERY_THING_TYPES_UIDS, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<ThingTypeUID> getSupportedThingTypes() {
|
||||||
|
return SUPPORTED_DISCOVERY_THING_TYPES_UIDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startScan() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBackgroundDiscoveryEnabled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generatorDiscovered(GeneratorStatusDTO generator, ThingUID bridgeUID) {
|
||||||
|
DiscoveryResult result = DiscoveryResultBuilder
|
||||||
|
.create(new ThingUID(GeneracMobileLinkBindingConstants.THING_TYPE_GENERATOR, bridgeUID,
|
||||||
|
String.valueOf(generator.gensetID)))
|
||||||
|
.withLabel("MobileLink Generator " + generator.generatorName)
|
||||||
|
.withProperty("generatorId", String.valueOf(generator.gensetID))
|
||||||
|
.withRepresentationProperty("generatorId").withBridge(bridgeUID).build();
|
||||||
|
thingDiscovered(result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ErrorResponseDTO} object from the MobileLink API
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
public class ErrorResponseDTO {
|
||||||
|
public Integer errorCode;
|
||||||
|
public String errorMessage;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link GeneratorStatusDTO} object from the MobileLink API
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
public class GeneratorStatusDTO {
|
||||||
|
public Integer gensetID;
|
||||||
|
public String generatorDate;
|
||||||
|
public String generatorName;
|
||||||
|
public String generatorSerialNumber;
|
||||||
|
public String generatorModel;
|
||||||
|
public String generatorDescription;
|
||||||
|
public String generatorMDN;
|
||||||
|
public String generatorImei;
|
||||||
|
public String generatorIccid;
|
||||||
|
public String generatorTetherSerial;
|
||||||
|
public Boolean connected;
|
||||||
|
public Boolean greenLightLit;
|
||||||
|
public Boolean yellowLightLit;
|
||||||
|
public Boolean redLightLit;
|
||||||
|
public Boolean blueLightLit;
|
||||||
|
public String generatorStatus;
|
||||||
|
public String generatorStatusDate;
|
||||||
|
public String currentAlarmDescription;
|
||||||
|
public Integer runHours;
|
||||||
|
public Integer exerciseHours;
|
||||||
|
public String batteryVoltage;
|
||||||
|
public Integer fuelType;
|
||||||
|
public Integer fuelLevel;
|
||||||
|
public String generatorBrandImageURL;
|
||||||
|
public Boolean generatorServiceStatus;
|
||||||
|
public String signalStrength;
|
||||||
|
public String deviceId;
|
||||||
|
public Integer deviceTypeId;
|
||||||
|
public String firmwareVersion;
|
||||||
|
public String timezone;
|
||||||
|
public String mACAddress;
|
||||||
|
public String iPAddress;
|
||||||
|
public String sSID;
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.dto;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link GeneratorStatusResponseDTO} response from the MobileLink API
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class GeneratorStatusResponseDTO extends ArrayList<GeneratorStatusDTO> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link LoginRequestDTO} request for the MobileLink API
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
public class LoginRequestDTO {
|
||||||
|
public LoginRequestDTO(String sharedKey, String userLogin, String userPassword) {
|
||||||
|
super();
|
||||||
|
this.sharedKey = sharedKey;
|
||||||
|
this.userLogin = userLogin;
|
||||||
|
this.userPassword = userPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sharedKey;
|
||||||
|
public String userLogin;
|
||||||
|
public String userPassword;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.dto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link LoginResponseDTO} response from the MobileLink API
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
public class LoginResponseDTO {
|
||||||
|
public String authToken;
|
||||||
|
public String pushChannelName;
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.factory;
|
||||||
|
|
||||||
|
import static org.openhab.binding.generacmobilelink.internal.GeneracMobileLinkBindingConstants.*;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.discovery.GeneracMobileLinkDiscoveryService;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.handler.GeneracMobileLinkAccountHandler;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.handler.GeneracMobileLinkGeneratorHandler;
|
||||||
|
import org.openhab.core.config.discovery.DiscoveryService;
|
||||||
|
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.ThingUID;
|
||||||
|
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||||
|
import org.osgi.framework.ServiceRegistration;
|
||||||
|
import org.osgi.service.component.annotations.Activate;
|
||||||
|
import org.osgi.service.component.annotations.Component;
|
||||||
|
import org.osgi.service.component.annotations.Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GeneracMobileLinkHandlerFactory} is responsible for creating things and thing
|
||||||
|
* handlers.
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
@Component(configurationPid = "binding.generacmobilelink", service = ThingHandlerFactory.class)
|
||||||
|
public class GeneracMobileLinkHandlerFactory extends BaseThingHandlerFactory {
|
||||||
|
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT,
|
||||||
|
THING_TYPE_GENERATOR);
|
||||||
|
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new ConcurrentHashMap<>();
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
|
@Activate
|
||||||
|
public GeneracMobileLinkHandlerFactory(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_GENERATOR.equals(thingTypeUID)) {
|
||||||
|
return new GeneracMobileLinkGeneratorHandler(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (THING_TYPE_ACCOUNT.equals(thingTypeUID)) {
|
||||||
|
GeneracMobileLinkDiscoveryService discoveryService = new GeneracMobileLinkDiscoveryService();
|
||||||
|
GeneracMobileLinkAccountHandler accountHandler = new GeneracMobileLinkAccountHandler((Bridge) thing,
|
||||||
|
httpClient, discoveryService);
|
||||||
|
discoveryServiceRegs.put(accountHandler.getThing().getUID(), bundleContext
|
||||||
|
.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
|
||||||
|
return accountHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected synchronized void removeHandler(ThingHandler thingHandler) {
|
||||||
|
if (thingHandler instanceof GeneracMobileLinkAccountHandler) {
|
||||||
|
ServiceRegistration<?> serviceReg = discoveryServiceRegs.remove(thingHandler.getThing().getUID());
|
||||||
|
if (serviceReg != null) {
|
||||||
|
serviceReg.unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.handler;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.eclipse.jetty.client.HttpClient;
|
||||||
|
import org.eclipse.jetty.client.api.ContentProvider;
|
||||||
|
import org.eclipse.jetty.client.api.Request;
|
||||||
|
import org.eclipse.jetty.client.api.Result;
|
||||||
|
import org.eclipse.jetty.client.util.BufferingResponseListener;
|
||||||
|
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||||
|
import org.eclipse.jetty.http.HttpMethod;
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.GeneracMobileLinkBindingConstants;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.config.GeneracMobileLinkAccountConfiguration;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.discovery.GeneracMobileLinkDiscoveryService;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.ErrorResponseDTO;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.GeneratorStatusDTO;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.GeneratorStatusResponseDTO;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.LoginRequestDTO;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.LoginResponseDTO;
|
||||||
|
import org.openhab.core.thing.Bridge;
|
||||||
|
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.ThingUID;
|
||||||
|
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||||
|
import org.openhab.core.thing.binding.ThingHandler;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.gson.FieldNamingPolicy;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GeneracMobileLinkAccountHandler} is responsible for connecting to the MobileLink cloud service and
|
||||||
|
* discovering generator things
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class GeneracMobileLinkAccountHandler extends BaseBridgeHandler {
|
||||||
|
private static final String BASE_URL = "https://api.mobilelinkgen.com";
|
||||||
|
private static final String SHARED_KEY = "GeneseeDepot13";
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(GeneracMobileLinkAccountHandler.class);
|
||||||
|
private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
|
||||||
|
private @Nullable Future<?> pollFuture;
|
||||||
|
private @Nullable String authToken;
|
||||||
|
private @Nullable GeneratorStatusResponseDTO generators;
|
||||||
|
private GeneracMobileLinkDiscoveryService discoveryService;
|
||||||
|
private HttpClient httpClient;
|
||||||
|
private int refreshIntervalSeconds = 60;
|
||||||
|
|
||||||
|
public GeneracMobileLinkAccountHandler(Bridge bridge, HttpClient httpClient,
|
||||||
|
GeneracMobileLinkDiscoveryService discoveryService) {
|
||||||
|
super(bridge);
|
||||||
|
this.httpClient = httpClient;
|
||||||
|
this.discoveryService = discoveryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
authToken = null;
|
||||||
|
restartPoll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
stopPoll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
updateGeneratorThings();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) {
|
||||||
|
GeneratorStatusResponseDTO generatorsLocal = generators;
|
||||||
|
if (generatorsLocal != null) {
|
||||||
|
Optional<GeneratorStatusDTO> generatorOpt = generatorsLocal.stream()
|
||||||
|
.filter(g -> String.valueOf(g.gensetID).equals(childThing.getUID().getId())).findFirst();
|
||||||
|
if (generatorOpt.isPresent()) {
|
||||||
|
((GeneracMobileLinkGeneratorHandler) childHandler).updateGeneratorStatus(generatorOpt.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopPoll() {
|
||||||
|
Future<?> localPollFuture = pollFuture;
|
||||||
|
if (localPollFuture != null) {
|
||||||
|
localPollFuture.cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restartPoll() {
|
||||||
|
stopPoll();
|
||||||
|
pollFuture = scheduler.scheduleWithFixedDelay(this::poll, 0, refreshIntervalSeconds, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void poll() {
|
||||||
|
try {
|
||||||
|
if (authToken == null) {
|
||||||
|
logger.debug("Attempting Login");
|
||||||
|
login();
|
||||||
|
}
|
||||||
|
getStatuses(true);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void login() throws InterruptedException {
|
||||||
|
GeneracMobileLinkAccountConfiguration config = getConfigAs(GeneracMobileLinkAccountConfiguration.class);
|
||||||
|
refreshIntervalSeconds = config.refreshInterval;
|
||||||
|
HTTPResult result = sendRequest(BASE_URL + "/Users/login", HttpMethod.POST, null,
|
||||||
|
new StringContentProvider(
|
||||||
|
gson.toJson(new LoginRequestDTO(SHARED_KEY, config.username, config.password))),
|
||||||
|
"application/json");
|
||||||
|
if (result.responseCode == HttpStatus.OK_200) {
|
||||||
|
LoginResponseDTO loginResponse = gson.fromJson(result.content, LoginResponseDTO.class);
|
||||||
|
if (loginResponse != null) {
|
||||||
|
authToken = loginResponse.authToken;
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
handleErrorResponse(result);
|
||||||
|
if (thing.getStatusInfo().getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR) {
|
||||||
|
// bad credentials, stop trying to login
|
||||||
|
stopPoll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getStatuses(boolean retry) throws InterruptedException {
|
||||||
|
if (authToken == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HTTPResult result = sendRequest(BASE_URL + "/Generator/GeneratorStatus", HttpMethod.GET, authToken, null, null);
|
||||||
|
if (result.responseCode == HttpStatus.OK_200) {
|
||||||
|
generators = gson.fromJson(result.content, GeneratorStatusResponseDTO.class);
|
||||||
|
updateGeneratorThings();
|
||||||
|
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (retry) {
|
||||||
|
logger.debug("Retrying status request");
|
||||||
|
getStatuses(false);
|
||||||
|
} else {
|
||||||
|
handleErrorResponse(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HTTPResult sendRequest(String url, HttpMethod method, @Nullable String token,
|
||||||
|
@Nullable ContentProvider content, @Nullable String contentType) throws InterruptedException {
|
||||||
|
try {
|
||||||
|
Request request = httpClient.newRequest(url).method(method).timeout(10, TimeUnit.SECONDS);
|
||||||
|
if (token != null) {
|
||||||
|
request = request.header("AuthToken", token);
|
||||||
|
}
|
||||||
|
if (content != null & contentType != null) {
|
||||||
|
request = request.content(content, contentType);
|
||||||
|
}
|
||||||
|
logger.trace("Sending {} to {}", request.getMethod(), request.getURI());
|
||||||
|
final CompletableFuture<HTTPResult> futureResult = new CompletableFuture<>();
|
||||||
|
request.send(new BufferingResponseListener() {
|
||||||
|
@NonNullByDefault({})
|
||||||
|
@Override
|
||||||
|
public void onComplete(Result result) {
|
||||||
|
futureResult.complete(new HTTPResult(result.getResponse().getStatus(), getContentAsString()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
HTTPResult result = futureResult.get();
|
||||||
|
logger.trace("Response - status: {} content: {}", result.responseCode, result.content);
|
||||||
|
return result;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
return new HTTPResult(0, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleErrorResponse(HTTPResult result) {
|
||||||
|
switch (result.responseCode) {
|
||||||
|
case HttpStatus.UNAUTHORIZED_401:
|
||||||
|
// the server responds with a 500 error in some cases when credentials are not correct
|
||||||
|
case HttpStatus.INTERNAL_SERVER_ERROR_500:
|
||||||
|
// server returned a valid error response
|
||||||
|
ErrorResponseDTO error = gson.fromJson(result.content, ErrorResponseDTO.class);
|
||||||
|
if (error != null && error.errorCode > 0) {
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||||
|
"Unauthorized: " + result.content);
|
||||||
|
authToken = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, result.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGeneratorThings() {
|
||||||
|
GeneratorStatusResponseDTO generatorsLocal = generators;
|
||||||
|
if (generatorsLocal != null) {
|
||||||
|
generatorsLocal.forEach(generator -> {
|
||||||
|
Thing thing = getThing().getThing(new ThingUID(GeneracMobileLinkBindingConstants.THING_TYPE_GENERATOR,
|
||||||
|
getThing().getUID(), String.valueOf(generator.gensetID)));
|
||||||
|
if (thing == null) {
|
||||||
|
discoveryService.generatorDiscovered(generator, getThing().getUID());
|
||||||
|
} else {
|
||||||
|
ThingHandler handler = thing.getHandler();
|
||||||
|
if (handler != null) {
|
||||||
|
((GeneracMobileLinkGeneratorHandler) handler).updateGeneratorStatus(generator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HTTPResult {
|
||||||
|
public @Nullable String content;
|
||||||
|
public final int responseCode;
|
||||||
|
|
||||||
|
public HTTPResult(int responseCode, @Nullable String content) {
|
||||||
|
this.responseCode = responseCode;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
* 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.generacmobilelink.internal.handler;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
|
||||||
|
import javax.measure.quantity.Time;
|
||||||
|
|
||||||
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import org.openhab.binding.generacmobilelink.internal.dto.GeneratorStatusDTO;
|
||||||
|
import org.openhab.core.library.types.DateTimeType;
|
||||||
|
import org.openhab.core.library.types.DecimalType;
|
||||||
|
import org.openhab.core.library.types.OnOffType;
|
||||||
|
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.binding.BaseThingHandler;
|
||||||
|
import org.openhab.core.types.Command;
|
||||||
|
import org.openhab.core.types.RefreshType;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link GeneracMobileLinkGeneratorHandler} is responsible for updating a generator things's channels
|
||||||
|
*
|
||||||
|
* @author Dan Cunningham - Initial contribution
|
||||||
|
*/
|
||||||
|
@NonNullByDefault
|
||||||
|
public class GeneracMobileLinkGeneratorHandler extends BaseThingHandler {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(GeneracMobileLinkGeneratorHandler.class);
|
||||||
|
private @Nullable GeneratorStatusDTO status;
|
||||||
|
|
||||||
|
public GeneracMobileLinkGeneratorHandler(Thing thing) {
|
||||||
|
super(thing);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||||
|
if (command instanceof RefreshType) {
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
updateStatus(ThingStatus.UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateGeneratorStatus(GeneratorStatusDTO status) {
|
||||||
|
this.status = status;
|
||||||
|
updateStatus(ThingStatus.ONLINE);
|
||||||
|
updateState();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateState() {
|
||||||
|
final GeneratorStatusDTO localStatus = status;
|
||||||
|
if (localStatus != null) {
|
||||||
|
updateState("connected", OnOffType.from(localStatus.connected));
|
||||||
|
updateState("greenLight", OnOffType.from(localStatus.greenLightLit));
|
||||||
|
updateState("yellowLight", OnOffType.from(localStatus.yellowLightLit));
|
||||||
|
updateState("redLight", OnOffType.from(localStatus.redLightLit));
|
||||||
|
updateState("blueLight", OnOffType.from(localStatus.blueLightLit));
|
||||||
|
try {
|
||||||
|
// API returns a format like 12/20/2020
|
||||||
|
updateState("statusDate",
|
||||||
|
new DateTimeType(LocalDate
|
||||||
|
.parse(localStatus.generatorStatusDate, DateTimeFormatter.ofPattern("MM/dd/yyyy"))
|
||||||
|
.atStartOfDay(ZoneId.systemDefault())));
|
||||||
|
} catch (IllegalArgumentException | DateTimeParseException e) {
|
||||||
|
logger.debug("Could not parse statusDate", e);
|
||||||
|
}
|
||||||
|
updateState("status", new StringType(localStatus.generatorStatus));
|
||||||
|
updateState("currentAlarmDescription", new StringType(localStatus.currentAlarmDescription));
|
||||||
|
updateState("runHours", new QuantityType<Time>(localStatus.runHours, Units.HOUR));
|
||||||
|
updateState("exerciseHours", new QuantityType<Time>(localStatus.exerciseHours, Units.HOUR));
|
||||||
|
updateState("fuelType", new DecimalType(localStatus.fuelType));
|
||||||
|
updateState("fuelLevel", QuantityType.valueOf(localStatus.fuelLevel, Units.PERCENT));
|
||||||
|
updateState("batteryVoltage", new StringType(localStatus.batteryVoltage));
|
||||||
|
updateState("serviceStatus", OnOffType.from(localStatus.generatorServiceStatus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<binding:binding id="generacmobilelink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||||
|
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||||
|
|
||||||
|
<name>GeneracMobileLink Binding</name>
|
||||||
|
<description>This binding monitors Generac manufactured generators through the MobileLink cloud service.</description>
|
||||||
|
|
||||||
|
</binding:binding>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<config-description:config-descriptions
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
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">
|
||||||
|
|
||||||
|
<config-description uri="thing-type:generacmobilelink:account">
|
||||||
|
<parameter name="username" type="text" required="true">
|
||||||
|
<label>Username</label>
|
||||||
|
<description>Account username</description>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="password" type="text" required="true">
|
||||||
|
<label>Password</label>
|
||||||
|
<description>Account password</description>
|
||||||
|
<context>password</context>
|
||||||
|
</parameter>
|
||||||
|
<parameter name="refreshInterval" type="integer" min="30" required="true" unit="s">
|
||||||
|
<label>Refresh Interval</label>
|
||||||
|
<description>Specifies the refresh interval in seconds</description>
|
||||||
|
<default>60</default>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
|
||||||
|
<config-description uri="thing-type:generacmobilelink:generator">
|
||||||
|
<parameter name="generatorId" type="text" required="true">
|
||||||
|
<label>Generator ID</label>
|
||||||
|
<description>Generator ID</description>
|
||||||
|
</parameter>
|
||||||
|
</config-description>
|
||||||
|
|
||||||
|
</config-description:config-descriptions>
|
|
@ -0,0 +1,109 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<thing:thing-descriptions bindingId="generacmobilelink"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
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">
|
||||||
|
|
||||||
|
<bridge-type id="account">
|
||||||
|
<label>MobileLink Account</label>
|
||||||
|
<description>MobileLink Cloud Account</description>
|
||||||
|
<config-description-ref uri="thing-type:generacmobilelink:account"/>
|
||||||
|
</bridge-type>
|
||||||
|
|
||||||
|
<thing-type id="generator">
|
||||||
|
<supported-bridge-type-refs>
|
||||||
|
<bridge-type-ref id="account"/>
|
||||||
|
</supported-bridge-type-refs>
|
||||||
|
<label>MobileLink Generator</label>
|
||||||
|
<description>MobileLink Generator</description>
|
||||||
|
<channels>
|
||||||
|
<channel id="connected" typeId="connected"/>
|
||||||
|
<channel id="greenLight" typeId="greenLight"/>
|
||||||
|
<channel id="yellowLight" typeId="yellowLight"/>
|
||||||
|
<channel id="redLight" typeId="redLight"/>
|
||||||
|
<channel id="blueLight" typeId="blueLight"/>
|
||||||
|
<channel id="statusDate" typeId="statusDate"/>
|
||||||
|
<channel id="status" typeId="status"/>
|
||||||
|
<channel id="currentAlarmDescription" typeId="currentAlarmDescription"/>
|
||||||
|
<channel id="runHours" typeId="runHours"/>
|
||||||
|
<channel id="exerciseHours" typeId="exerciseHours"/>
|
||||||
|
<channel id="fuelType" typeId="fuelType"/>
|
||||||
|
<channel id="fuelLevel" typeId="fuelLevel"/>
|
||||||
|
<channel id="batteryVoltage" typeId="batteryVoltage"/>
|
||||||
|
<channel id="serviceStatus" typeId="serviceStatus"/>
|
||||||
|
</channels>
|
||||||
|
<representation-property>generatorId</representation-property>
|
||||||
|
<config-description-ref uri="thing-type:generacmobilelink:generator"/>
|
||||||
|
</thing-type>
|
||||||
|
|
||||||
|
<channel-type id="connected">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Connected</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="greenLight">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Green Light Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="yellowLight">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Yellow Light Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="redLight">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Red Light Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="blueLight">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Blue Light Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="statusDate">
|
||||||
|
<item-type>DateTime</item-type>
|
||||||
|
<label>Last Status Date</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="status">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="currentAlarmDescription">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Current Alarm Description</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="runHours">
|
||||||
|
<item-type>Number:Time</item-type>
|
||||||
|
<label>Number of Hours Run</label>
|
||||||
|
<state readOnly="true" pattern="%d %unit%"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="exerciseHours">
|
||||||
|
<item-type>Number:Time</item-type>
|
||||||
|
<label>Number of Hours Exercised</label>
|
||||||
|
<state readOnly="true" pattern="%d %unit%"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="fuelType">
|
||||||
|
<item-type>Number</item-type>
|
||||||
|
<label>Fuel Type</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="fuelLevel">
|
||||||
|
<item-type>Number:Dimensionless</item-type>
|
||||||
|
<label>Fuel Level</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="batteryVoltage">
|
||||||
|
<item-type>String</item-type>
|
||||||
|
<label>Battery Voltage Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
<channel-type id="serviceStatus">
|
||||||
|
<item-type>Switch</item-type>
|
||||||
|
<label>Service Status</label>
|
||||||
|
<state readOnly="true"/>
|
||||||
|
</channel-type>
|
||||||
|
</thing:thing-descriptions>
|
|
@ -111,6 +111,7 @@
|
||||||
<module>org.openhab.binding.ftpupload</module>
|
<module>org.openhab.binding.ftpupload</module>
|
||||||
<module>org.openhab.binding.gardena</module>
|
<module>org.openhab.binding.gardena</module>
|
||||||
<module>org.openhab.binding.gce</module>
|
<module>org.openhab.binding.gce</module>
|
||||||
|
<module>org.openhab.binding.generacmobilelink</module>
|
||||||
<module>org.openhab.binding.goecharger</module>
|
<module>org.openhab.binding.goecharger</module>
|
||||||
<module>org.openhab.binding.globalcache</module>
|
<module>org.openhab.binding.globalcache</module>
|
||||||
<module>org.openhab.binding.gpstracker</module>
|
<module>org.openhab.binding.gpstracker</module>
|
||||||
|
|
Loading…
Reference in New Issue