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

[renault] Initial Contribution #11467

Merged
merged 16 commits into from
Dec 5, 2021
Merged
Show file tree
Hide file tree
Changes from 15 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
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@
/bundles/org.openhab.binding.regoheatpump/ @crnjan
/bundles/org.openhab.binding.revogi/ @andibraeu
/bundles/org.openhab.binding.remoteopenhab/ @lolodomo
/bundles/org.openhab.binding.renault/ @dougculnane
/bundles/org.openhab.binding.resol/ @ramack
/bundles/org.openhab.binding.rfxcom/ @martinvw @paulianttila
/bundles/org.openhab.binding.rme/ @kgoderis
Expand Down
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,11 @@
<artifactId>org.openhab.binding.remoteopenhab</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.renault</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.resol</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.renault/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
43 changes: 43 additions & 0 deletions bundles/org.openhab.binding.renault/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Renault Binding

This binding allow MyRenault App. users to get battery status and other data from their cars.

A binding that translates the [python based renault-api](https://renault-api.readthedocs.io/en/latest/) in an easy to use binding.


## Supported Things

Supports MyRenault registered cars with an active Connected-Services account.

This binding can only retrieve information that is available in the the MyRenault App.


## Discovery

No discovery

## Thing Configuration

You require your MyRenault credential, locale and VIN for your MyRenault registered car.

| Parameter | Description | Required |
|-------------------|----------------------------------------|----------|
| myRenaultUsername | MyRenault Username. | yes |
| myRenaultPassword | MyRenault Password. | yes |
| locale | MyRenault Location (language_country). | yes |
| vin | Vehicle Identification Number. | yes |
| refreshInterval | Interval the car is polled in minutes. | no |

## Channels

Currently all available channels are read only:

| Channel ID | Type | Description |
|--------------|---------------|---------------------------------|
| batterylevel | Number | State of the battery in % |
| hvacstatus | Switch | HVAC status switch |
| image | String | Image URL of MyRenault |
| location | Location | The GPS position of the vehicle |
| odometer | Number:Length | Total distance travelled |


17 changes: 17 additions & 0 deletions bundles/org.openhab.binding.renault/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.2.0-SNAPSHOT</version>
</parent>

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

<name>openHAB Add-ons :: Bundles :: Renault 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.renault-${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-renault" description="Renault Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.renault/${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.renault.internal;

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

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

private static final String BINDING_ID = "renault";

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_CAR = new ThingTypeUID(BINDING_ID, "car");

// List of all Channel ids
public static final String CHANNEL_BATTERY_LEVEL = "batterylevel";
public static final String CHANNEL_HVAC_STATUS = "hvacstatus";
public static final String CHANNEL_IMAGE = "image";
public static final String CHANNEL_LOCATION = "location";
public static final String CHANNEL_ODOMETER = "odometer";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* 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.renault.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link RenaultConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Doug Culnane - Initial contribution
*/
@NonNullByDefault
public class RenaultConfiguration {
lolodomo marked this conversation as resolved.
Show resolved Hide resolved

public String myRenaultUsername = "";
public String myRenaultPassword = "";
public String locale = "";
public String vin = "";
public int refreshInterval = 10;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* 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.renault.internal;

import static org.openhab.binding.renault.internal.RenaultBindingConstants.*;

import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.renault.internal.handler.RenaultHandler;
import org.openhab.core.io.net.http.HttpClientFactory;
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 RenaultHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Doug Culnane - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.renault", service = ThingHandlerFactory.class)
public class RenaultHandlerFactory extends BaseThingHandlerFactory {

private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_CAR);

private final HttpClient httpClient;

@Activate
public RenaultHandlerFactory(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_CAR.equals(thingTypeUID)) {
return new RenaultHandler(thing, httpClient);
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/**
* 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.renault.internal.api;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

/**
* MyRenault registered car for parsing HTTP responses and collecting data and
* information.
*
* @author Doug Culnane - Initial contribution
*/
@NonNullByDefault
public class Car {

private final Logger logger = LoggerFactory.getLogger(Car.class);

public boolean disableLocation = false;
public boolean disableBattery = false;
public boolean disableCockpit = false;
public boolean disableHvac = false;
lolodomo marked this conversation as resolved.
Show resolved Hide resolved

public @Nullable Double batteryLevel;
public @Nullable Boolean hvacstatus;
public @Nullable Double odometer;
public @Nullable String imageURL;
public @Nullable Double gpsLatitude;
public @Nullable Double gpsLongitude;
lolodomo marked this conversation as resolved.
Show resolved Hide resolved

public void setBatteryStatus(JsonObject responseJson) {
try {
JsonObject attributes = getAttributes(responseJson);
if (attributes != null && attributes.get("batteryLevel") != null) {
batteryLevel = attributes.get("batteryLevel").getAsDouble();
}
} catch (IllegalStateException | ClassCastException e) {
logger.warn("Error {} parsing Battery Status: {}", e.getMessage(), responseJson);
}
}

public void setHVACStatus(JsonObject responseJson) {
try {
JsonObject attributes = getAttributes(responseJson);
if (attributes != null && attributes.get("hvacStatus") != null) {
hvacstatus = attributes.get("hvacStatus").getAsString().equals("on");
}
} catch (IllegalStateException | ClassCastException e) {
logger.warn("Error {} parsing HVAC Status: {}", e.getMessage(), responseJson);
}
}

public void setCockpit(JsonObject responseJson) {
try {
JsonObject attributes = getAttributes(responseJson);
if (attributes != null && attributes.get("totalMileage") != null) {
odometer = attributes.get("totalMileage").getAsDouble();
}
} catch (IllegalStateException | ClassCastException e) {
logger.warn("Error {} parsing Cockpit: {}", e.getMessage(), responseJson);
}
}

public void setLocation(JsonObject responseJson) {
try {
JsonObject attributes = getAttributes(responseJson);
if (attributes != null) {
if (attributes.get("gpsLatitude") != null) {
gpsLatitude = attributes.get("gpsLatitude").getAsDouble();
}
if (attributes.get("gpsLongitude") != null) {
gpsLongitude = attributes.get("gpsLongitude").getAsDouble();
}
}
} catch (IllegalStateException | ClassCastException e) {
logger.warn("Error {} parsing Location: {}", e.getMessage(), responseJson);
}
}

public void setDetails(JsonObject responseJson) {
try {
if (responseJson.get("assets") != null) {
JsonArray assetsJson = responseJson.get("assets").getAsJsonArray();
String url = null;
for (JsonElement asset : assetsJson) {
if (asset.getAsJsonObject().get("assetType") != null
&& asset.getAsJsonObject().get("assetType").getAsString().equals("PICTURE")) {
if (asset.getAsJsonObject().get("renditions") != null) {
JsonArray renditions = asset.getAsJsonObject().get("renditions").getAsJsonArray();
for (JsonElement rendition : renditions) {
if (rendition.getAsJsonObject().get("resolutionType") != null
&& rendition.getAsJsonObject().get("resolutionType").getAsString()
.equals("ONE_MYRENAULT_SMALL")) {
url = rendition.getAsJsonObject().get("url").getAsString();
break;
}
}
}
}
if (url != null && !url.isEmpty()) {
imageURL = url;
break;
}
}
}
} catch (IllegalStateException | ClassCastException e) {
logger.warn("Error {} parsing Details: {}", e.getMessage(), responseJson);
}
}

private @Nullable JsonObject getAttributes(JsonObject responseJson)
throws IllegalStateException, ClassCastException {
if (responseJson.get("data") != null && responseJson.get("data").getAsJsonObject().get("attributes") != null) {
return responseJson.get("data").getAsJsonObject().get("attributes").getAsJsonObject();
}
return null;
}
}
Loading