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

[casokitchen] Initial contribution #18243

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
/bundles/org.openhab.binding.bticinosmarther/ @MrRonfo
/bundles/org.openhab.binding.buienradar/ @gedejong
/bundles/org.openhab.binding.caddx/ @jossuar
/bundles/org.openhab.binding.casokitchen/ @weymann
/bundles/org.openhab.binding.cbus/ @jpharvey
/bundles/org.openhab.binding.chatgpt/ @kaikreuzer
/bundles/org.openhab.binding.chromecast/ @kaikreuzer
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 @@ -306,6 +306,11 @@
<artifactId>org.openhab.binding.caddx</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.casokitchen</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.cbus</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.casokitchen/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
86 changes: 86 additions & 0 deletions bundles/org.openhab.binding.casokitchen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# CasoKitchen Binding

Provides access towards CASO Smart Kitchen devices which are connected within the [CASO Control App](https://www.casocontrol.de/).

## Supported Things

- `winecooler-2z`: Wine cooler with two zones

## Discovery

There's no automatic discovery.

## Thing Configuration

You need a [CASO Account](https://www.casoapp.com/Account/Create) to get configuration parameters.
After register you'll get the

- API key
- Device ID

## Wine Cooler with 2 Zones

### Configuration winecooler-2z

| Name | Type | Description | Default |
|-----------------|---------|------------------------------------------------------|---------|
| apiKey | text | API obtained from thing configuration | N/A |
| deviceId | text | Device Id obtained from thing configuration | N/A |
| refreshInterval | integer | Interval the device is polled in minutes | 5 |

### Channels winecooler-2z

Channels are separated in 3 groups

- `generic` group covering states for the whole device
- `top` and `bottom` group covering states related to top or bottom zone

#### Generic Group

Group name `generic`.

| Channel | Type | Read/Write | Description |
|---------------|----------|------------|------------------------------|
| light-switch | Switch | RW | Control lights for all zones |
| last-update | DateTime | R | Date and Time of last update |
| hint | String | R | General command description |

#### Zone Groups

Group `top` and `bottom`.

The `set-temperature` channel is holding the desired temperature controlled via buttons on the wine cooler device.
Currently it cannot be changed using the API.

| Channel | Type | Read/Write | Description |
|------------------|-----------------------|------------|------------------------------|
| power | Switch | R | Zone Power |
| temperature | Number:Temperature | R | Current Zone Temperature |
| set-temperature | Number:Temperature | R | Desired Zone Temperature |
| light-switch | Switch | RW | Control lights for this zone |

## Full Example

### Thing Configuration

```java
Thing casokitchen:winecooler-2z:whiny "Whiny Wine Cooler" [ apiKey="ABC", deviceId="XYZ" ]
```

### Item Configuration

```java
Switch Whiny_Generic_LightSwitch {channel="casokitchen:winecooler-2z:whiny:generic#light-switch" }
DateTime Whiny_Generic_LastUpdate {channel="casokitchen:winecooler-2z:whiny:generic#last-update" }
String Whiny_Generic_Hint {channel="casokitchen:winecooler-2z:whiny:generic#hint" }

Switch Whiny_Top_Power {channel="casokitchen:winecooler-2z:whiny:top#power" }
Number:Temperature Whiny_Top_CurrentTemperature {channel="casokitchen:winecooler-2z:whiny:top#temperature" }
Number:Temperature Whiny_Top_DesiredTemperature {channel="casokitchen:winecooler-2z:whiny:top#set-temperature" }
Switch Whiny_Top_LightSwitch {channel="casokitchen:winecooler-2z:whiny:top#light-switch" }

Switch Whiny_Bottom_Power {channel="casokitchen:winecooler-2z:whiny:bottom#power" }
Number:Temperature Whiny_Bottom_CurrentTemperature {channel="casokitchen:winecooler-2z:whiny:bottom#temperature" }
Number:Temperature Whiny_Bottom_DesiredTemperature {channel="casokitchen:winecooler-2z:whiny:bottom#set-temperature" }
Switch Whiny_Bottom_LightSwitch {channel="casokitchen:winecooler-2z:whiny:bottom#light-switch" }
```
17 changes: 17 additions & 0 deletions bundles/org.openhab.binding.casokitchen/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 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>5.0.0-SNAPSHOT</version>
</parent>

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

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

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

import com.google.gson.Gson;

/**
* The {@link CasoKitchenBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Bernd Weymann - Initial contribution
*/
@NonNullByDefault
public class CasoKitchenBindingConstants {
private static final String BINDING_ID = "casokitchen";

// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_WINECOOLER = new ThingTypeUID(BINDING_ID, "winecooler-2z");

// List of all Channel Group ids
public static final String TOP = "top";
public static final String BOTTOM = "bottom";
public static final String GENERIC = "generic";

// List of all Channel ids
public static final String TEMPERATURE = "temperature";
public static final String TARGET_TEMPERATURE = "set-temperature";
public static final String POWER = "power";
public static final String LIGHT = "light-switch";
public static final String HINT = "hint";
public static final String LAST_UPDATE = "last-update";

public static final String EMPTY = "";

public static final String BASE_URL = "https://publickitchenapi.casoapp.com";
public static final String LIGHT_URL = BASE_URL + "/api/v1.1/Winecooler/SetLight";
public static final String STATUS_URL = BASE_URL + "/api/v1.1/Winecooler/Status";
public static final String HTTP_HEADER_API_KEY = "x-api-key";

public static final Gson GSON = new Gson();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright (c) 2010-2025 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.casokitchen.internal;

import static org.openhab.binding.casokitchen.internal.CasoKitchenBindingConstants.THING_TYPE_WINECOOLER;

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.casokitchen.internal.handler.TwoZonesWinecoolerHandler;
import org.openhab.core.i18n.TimeZoneProvider;
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 CasoKitchenHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Bernd Weymann - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.casokitchen", service = ThingHandlerFactory.class)
public class CasoKitchenHandlerFactory extends BaseThingHandlerFactory {

private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_WINECOOLER);
private HttpClient httpClient;
private TimeZoneProvider timeZoneProvider;

@Activate
public CasoKitchenHandlerFactory(final @Reference HttpClientFactory httpClientFactory,
final @Reference TimeZoneProvider tzp) {
httpClient = httpClientFactory.getCommonHttpClient();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please store the factory and create a httpclient for each time a thing handler is created.

timeZoneProvider = tzp;
}

@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_WINECOOLER.equals(thingTypeUID)) {
return new TwoZonesWinecoolerHandler(thing, httpClient, timeZoneProvider);
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2010-2025 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.casokitchen.internal.config;

import static org.openhab.binding.casokitchen.internal.CasoKitchenBindingConstants.EMPTY;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link TwoZonesWinecoolerConfiguration} class contains fields mapping thing configuration parameters.
*
* @author Bernd Weymann - Initial contribution
*/
@NonNullByDefault
public class TwoZonesWinecoolerConfiguration {
public String apiKey = EMPTY;
public String deviceId = EMPTY;
public int refreshInterval = 5;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2010-2025 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.casokitchen.internal.dto;

import static org.openhab.binding.casokitchen.internal.CasoKitchenBindingConstants.EMPTY;

import org.eclipse.jdt.annotation.NonNullByDefault;

/**
* The {@link LightRequest} class contains fields mapping thing configuration parameters.
*
* @author Bernd Weymann - Initial contribution
*/
@NonNullByDefault
public class LightRequest {
public String technicalDeviceId = EMPTY;
public int zone = -1;
public boolean lightOn = false;

public boolean isValid() {
return !technicalDeviceId.equals(EMPTY) && zone >= 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2010-2025 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.casokitchen.internal.dto;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.casokitchen.internal.CasoKitchenBindingConstants;

/**
* The {@link StatusRequest} class contains fields mapping thing configuration parameters.
*
* @author Bernd Weymann - Initial contribution
*/
@NonNullByDefault
public class StatusRequest {

public StatusRequest(String intialValue) {
technicalDeviceId = intialValue;
}

public String technicalDeviceId = CasoKitchenBindingConstants.EMPTY;
}
Loading