]> git.basschouten.com Git - openhab-addons.git/commitdiff
[fpp] Initial contribution (#16298)
authorScott Hanson <computergeek1507@users.noreply.github.com>
Fri, 20 Sep 2024 18:59:10 +0000 (14:59 -0400)
committerGitHub <noreply@github.com>
Fri, 20 Sep 2024 18:59:10 +0000 (20:59 +0200)
* working on FPP

Signed-off-by: Scott Hanson <scooter_seh@yahoo.com>
19 files changed:
CODEOWNERS
bundles/org.openhab.binding.mqtt.fpp/NOTICE [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/README.md [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/pom.xml [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/feature/feature.xml [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/ConfigOptions.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPBindingConstants.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPHandlerFactory.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPStatus.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPCurrentPlaylist.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPNextPlaylist.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPPlaylist.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPScheduler.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/handler/FPPPlayerHandler.java [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/config/config.xml [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/i18n/mqtt.properties [new file with mode: 0644]
bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/thing/thing-types.xml [new file with mode: 0644]
bundles/pom.xml
features/openhab-addons/src/main/resources/footer.xml

index 486a1c2e5d6d8f102a180454f8bd428e10bb65f0..28ec2b43f63d907e25ba53dd8564d54f3a85593d 100755 (executable)
 /bundles/org.openhab.binding.mpd/ @stefanroellin
 /bundles/org.openhab.binding.mqtt/ @ccutrer
 /bundles/org.openhab.binding.mqtt.espmilighthub/ @Skinah
+/bundles/org.openhab.binding.mqtt.fpp/ @computergeek1507
 /bundles/org.openhab.binding.mqtt.generic/ @ccutrer
 /bundles/org.openhab.binding.mqtt.homeassistant/ @antroids @ccutrer
 /bundles/org.openhab.binding.mqtt.homie/ @ccutrer
diff --git a/bundles/org.openhab.binding.mqtt.fpp/NOTICE b/bundles/org.openhab.binding.mqtt.fpp/NOTICE
new file mode 100644 (file)
index 0000000..38d625e
--- /dev/null
@@ -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
diff --git a/bundles/org.openhab.binding.mqtt.fpp/README.md b/bundles/org.openhab.binding.mqtt.fpp/README.md
new file mode 100644 (file)
index 0000000..19d46ca
--- /dev/null
@@ -0,0 +1,92 @@
+# FPP Binding
+
+Binding to control Falcon Player (FPP) Devices using MQTT and HTTP. Status messages are recieved over MQTT and Commands are HTTP Commands.
+
+## Discovery
+
+Autodiscovering is not supported. We have to define the things manually.
+
+## Supported Things
+
+The binding supports one Thing `player` that represents the Falcon Player.
+## Thing Configuration
+
+| Parameter    | Description                             | Required | Default |
+|--------------|-----------------------------------------|----------|---------|
+| `playerIP`   | IP Address or Host Name of FPP Devive   | Y        |         |
+| `playerMQTT` | MQTT Topic of FPP Devive Status Updates | Y        |         |
+
+## Channels
+
+| Channel                                | Type               | Description                               |
+|----------------------------------------|--------------------|-------------------------------------------|
+| `player`                               | Player             | Play/Stop Current Playlist.               |
+| `volume`                               | Dimmer             | Playback Audio Volume.                    |
+| `status`                               | String             | Playback Status.                          |
+| `mode`                                 | String             | Playback Mode.                            |
+| `uptime`                               | Number:Time        | Device Uptime.                            |
+| `testing-enabled`                      | Switch             | Enabled/Disable Sending Testing Data.     |
+| `current-sequence`                     | String (read only) | Currently Playing Sequence File.          |
+| `current-song`                         | String (read only) | Currently Playing Audio/Media File.       |
+| `current-playlist`                     | String (read only) | Currently Playing Playlist.               |
+| `seconds-played`                       | Number:Time        | Sequence Playback time in secs.           |
+| `seconds-remaining`                    | Number:Time        | Sequence Playback time remaining in secs. |
+| `last-playlist`                        | String             | Lasted Played Playlist.                   |
+| `bridging-enabled`                     | Switch             | Is Recieving Bridge Data.                 |
+| `multisync-enabled`                    | Switch             | Multisync Mode Enabled.                   |
+| `scheduler-current-playlist`           | String (read only) | Scheduler Current Playlist.               |
+| `scheduler-current-playlist-start`     | String (read only) | Scheduler Current Playlist Start Time.    |
+| `scheduler-current-playlist-end`       | String (read only) | Scheduler Current Playlist End Time.      |
+| `scheduler-current-playlist-stop-type` | String (read only) | Scheduler Current Playlist End Type.      |
+| `scheduler-next-playlist`              | String (read only) | Next Scheduled Playlist.                  |
+| `scheduler-next-playlist-start`        | String (read only) | Next Scheduled Start Time.                |
+
+
+## Full Example
+
+To use these examples for textual configuration, you must already have a configured MQTT `broker` thing, and know its unique ID.
+This UID will be used in the things file and will replace the text `myBroker`.
+The first line in the things file will create a `broker` thing and this can be removed if you have already setup a broker in another file or via the UI already.
+
+### fpp.things
+
+```java
+Bridge mqtt:broker:myBroker [ host="localhost", secure=false, password="*******", qos=1, username="user"]
+Thing mqtt:player:myBroker:mainPlayer "Main Player" (mqtt:broker:myBroker) @ "MQTT"
+```
+
+### fpp.items
+
+```java
+Player FPP_Player "FPP Player" {channel="mqtt:player:myBroker:mainPlayer:player"}
+Dimmer Audio_Volume "Audio Volume" {channel="mqtt:player:myBroker:mainPlayer:volume"}
+String Current_Sequence "Current Sequence" {channel="mqtt:player:myBroker:mainPlayer:current-sequence"}
+String Current_Song "Current Song" {channel="mqtt:player:myBroker:mainPlayer:current-song"}
+String Current_Playlist "Current Playlist" {channel="mqtt:player:myBroker:mainPlayer:current-playlist"}
+String Status "FPP Status" {channel="mqtt:player:myBroker:mainPlayer:status"}
+String Mode "FPP Mode" {channel="mqtt:player:myBroker:mainPlayer:mode"}
+String Last_Playlist "Last Playlist" {channel="mqtt:player:myBroker:mainPlayer:last-playlist"}
+Number:Time Seconds_Played "Seconds Played [%d %unit%]" {channel="mqtt:player:myBroker:mainPlayer:seconds-played"}
+Number:Time Seconds_Remaining "Seconds Remaining [%d %unit%]" {channel="mqtt:player:myBroker:mainPlayer:seconds-remaining"}
+Switch Testing "Testing Mode" {channel="mqtt:player:myBroker:mainPlayer:testing-enabled"}
+Switch Multisync "Multisync" {channel="mqtt:player:myBroker:mainPlayer:multisync-enabled"}
+```
+
+### fpp.sitemap
+
+```perl
+Text label="Main Player"
+{
+    Player      item=FPP_Player
+    Switch      item=Testing
+    Slider      item=Audio_Volume
+    Text        item=Current_Sequence
+    Text        item=Current_Song
+    Text        item=Current_Playlist
+    Text        item=Status
+    Text        item=Mode
+    Selection   item=Last_Playlist
+    Switch      item=Testing
+    Switch      item=Multisync
+}
+```
diff --git a/bundles/org.openhab.binding.mqtt.fpp/pom.xml b/bundles/org.openhab.binding.mqtt.fpp/pom.xml
new file mode 100644 (file)
index 0000000..b6c67c8
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.openhab.addons.bundles</groupId>
+    <artifactId>org.openhab.addons.reactor.bundles</artifactId>
+    <version>4.3.0-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>org.openhab.binding.mqtt.fpp</artifactId>
+  <name>openHAB Add-ons :: Bundles :: MQTT FPP</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.openhab.addons.bundles</groupId>
+      <artifactId>org.openhab.binding.mqtt</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/feature/feature.xml b/bundles/org.openhab.binding.mqtt.fpp/src/main/feature/feature.xml
new file mode 100644 (file)
index 0000000..ca8ff9f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<features name="org.openhab.binding.mqtt.fpp-${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-mqtt-fpp" description="MQTT Binding FPP" version="${project.version}">
+               <feature>openhab-runtime-base</feature>
+               <feature>openhab-transport-mqtt</feature>
+               <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version}</bundle>
+               <bundle start-level="81">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.fpp/${project.version}</bundle>
+       </feature>
+
+</features>
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/ConfigOptions.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/ConfigOptions.java
new file mode 100644 (file)
index 0000000..9ffcada
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link ConfigOptions} Holds the config for the settings.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+@NonNullByDefault
+public class ConfigOptions {
+    public String playerAddress = "";
+    public String playerMQTTTopic = "";
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPBindingConstants.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPBindingConstants.java
new file mode 100644 (file)
index 0000000..9c27ea3
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import static org.openhab.binding.mqtt.MqttBindingConstants.BINDING_ID;
+
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.ThingTypeUID;
+
+/**
+ * The {@link FPPBindingConstants} class defines common constants, which are
+ * used across the whole binding.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+@NonNullByDefault
+public class FPPBindingConstants {
+    // falcon/player/FPP/fppd_status
+    public static final String STATUS_TOPIC = "fppd_status";
+    public static final String VERSION_TOPIC = "version";
+    public static final String PLAYLIST_TOPIC = "playlist";
+    public static final String MQTT_PREFIX = "falcon/player/";
+
+    // List of all Thing Type UIDs
+    public static final ThingTypeUID THING_TYPE_PLAYER = new ThingTypeUID(BINDING_ID, "player");
+
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_PLAYER);
+
+    // Channels
+    public static final String CHANNEL_PLAYER = "player";
+    public static final String CHANNEL_STATUS = "status";
+    public static final String CHANNEL_VOLUME = "volume";
+    public static final String CHANNEL_MODE = "mode";
+    public static final String CHANNEL_CURRENT_SEQUENCE = "current-sequence";
+    public static final String CHANNEL_CURRENT_SONG = "current-song";
+    public static final String CHANNEL_CURRENT_PLAYLIST = "current-playlist";
+    public static final String CHANNEL_SEC_PLAYED = "seconds-played";
+    public static final String CHANNEL_SEC_REMAINING = "seconds-remaining";
+    public static final String CHANNEL_UPTIME = "uptime";
+    public static final String CHANNEL_BRIDGING = "bridging-enabled";
+    public static final String CHANNEL_MULTISYNC = "multisync-enabled";
+    public static final String CHANNEL_TESTING = "testing-enabled";
+    public static final String CHANNEL_LAST_PLAYLIST = "last-playlist";
+
+    public static final String CHANNEL_SCHEDULER_STATUS = "scheduler-status";
+    public static final String CHANNEL_SCHEDULER_CURRENT_PLAYLIST = "scheduler-current-playlist";
+    public static final String CHANNEL_SCHEDULER_CURRENT_PLAYLIST_START = "scheduler-current-playlist-start";
+    public static final String CHANNEL_SCHEDULER_CURRENT_PLAYLIST_END = "scheduler-current-playlist-end";
+    public static final String CHANNEL_SCHEDULER_CURRENT_PLAYLIST_STOP_TYPE = "scheduler-current-playlist-stop-type";
+    public static final String CHANNEL_SCHEDULER_NEXT_PLAYLIST = "scheduler-next-playlist";
+    public static final String CHANNEL_SCHEDULER_NEXT_PLAYLIST_START = "scheduler-next-playlist-start";
+
+    public static final String PROPERTY_UUID = "uuid";
+    public static final String PROPERTY_SOFTWARE_VERSION = "Software Version";
+
+    // Status
+    public static final String CONNECTED = "connected";
+    public static final String CHANNEL_STATUS_NAME = "status-name";
+
+    public static final String TESTING = "testing";
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPHandlerFactory.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPHandlerFactory.java
new file mode 100644 (file)
index 0000000..96d132f
--- /dev/null
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import static org.openhab.binding.mqtt.fpp.internal.FPPBindingConstants.SUPPORTED_THING_TYPES;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.mqtt.fpp.internal.handler.FPPPlayerHandler;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingRegistry;
+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 FPPHandlerFactory} is responsible for creating things and thing
+ * handlers.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+@Component(service = ThingHandlerFactory.class)
+@NonNullByDefault
+public class FPPHandlerFactory extends BaseThingHandlerFactory {
+    private final ThingRegistry thingRegistry;
+
+    @Activate
+    public FPPHandlerFactory(final @Reference ThingRegistry thingRegistry) {
+        this.thingRegistry = thingRegistry;
+    }
+
+    @Override
+    public boolean supportsThingType(ThingTypeUID thingTypeUID) {
+        return SUPPORTED_THING_TYPES.contains(thingTypeUID);
+    }
+
+    @Override
+    protected @Nullable ThingHandler createHandler(Thing thing) {
+        ThingTypeUID thingTypeUID = thing.getThingTypeUID();
+        if (SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
+            return new FPPPlayerHandler(thing, thingRegistry);
+        }
+        return null;
+    }
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPStatus.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/FPPStatus.java
new file mode 100644 (file)
index 0000000..25adf6d
--- /dev/null
@@ -0,0 +1,156 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link FPPStstus} is responsible for storing
+ * the FPP JSON Status data.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+public class FPPStatus {
+    /*
+     * {
+     * "MQTT" :
+     * {
+     * "configured" : true,
+     * "connected" : true
+     * },
+     * "bridging" : false,
+     * "current_playlist" :
+     * {
+     * "count" : "0",
+     * "description" : "",
+     * "index" : "0",
+     * "playlist" : "",
+     * "type" : ""
+     * },
+     * "current_sequence" : "",
+     * "current_song" : "",
+     * "dateStr" : "Sun Jan  7",
+     * "fppd" : "running",
+     * "mode" : 2,
+     * "mode_name" : "player",
+     * "multisync" : true,
+     * "next_playlist" :
+     * {
+     * "playlist" : "No playlist scheduled.",
+     * "start_time" : ""
+     * },
+     * "repeat_mode" : "0",
+     * "scheduler" :
+     * {
+     * "enabled" : 1,
+     * "nextPlaylist" :
+     * {
+     * "playlistName" : "No playlist scheduled.",
+     * "scheduledStartTime" : 0,
+     * "scheduledStartTimeStr" : ""
+     * },
+     * "status" : "idle"
+     * },
+     * "seconds_played" : "0",
+     * "seconds_remaining" : "0",
+     * "sensors" :
+     * [
+     * {
+     * "formatted" : "55.0",
+     * "label" : "CPU: ",
+     * "postfix" : "",
+     * "prefix" : "",
+     * "value" : 55.017000000000003,
+     * "valueType" : "Temperature"
+     * }
+     * ],
+     * "status" : 0,
+     * "status_name" : "idle",
+     * "time" : "Sun Jan 07 19:15:25 EST 2024",
+     * "timeStr" : "07:15 PM",
+     * "timeStrFull" : "07:15:25 PM",
+     * "time_elapsed" : "00:00",
+     * "time_remaining" : "00:00",
+     * "uptime" : "2 days, 01:30:04",
+     * "uptimeDays" : 2.0625462962962962,
+     * "uptimeHours" : 1.5011111111111111,
+     * "uptimeMinutes" : 30.066666666666666,
+     * "uptimeSeconds" : 4,
+     * "uptimeStr" : "2 days, 1 hours, 30 minutes, 4 seconds",
+     * "uptimeTotalSeconds" : 178204,
+     * "uuid" : "M1-10000000fd93cfe5",
+     * "volume" : 48
+     * }
+     * 
+     */
+    @SerializedName("status")
+    @Expose
+    public int status;
+
+    @SerializedName("status_name")
+    @Expose
+    public String status_name;
+
+    @SerializedName("mode_name")
+    @Expose
+    public String mode_name;
+
+    @SerializedName("current_sequence")
+    @Expose
+    public String current_sequence;
+
+    @SerializedName("current_song")
+    @Expose
+    public String current_song;
+
+    @SerializedName("time_elapsed")
+    @Expose
+    public String time_elapsed;
+
+    @SerializedName("uptimeTotalSeconds")
+    @Expose
+    public long uptimeTotalSeconds;
+
+    @SerializedName("seconds_played")
+    @Expose
+    public int seconds_played;
+
+    @SerializedName("seconds_remaining")
+    @Expose
+    public int seconds_remaining;
+
+    @SerializedName("volume")
+    @Expose
+    public int volume;
+
+    @SerializedName("uuid")
+    @Expose
+    public String uuid;
+
+    @SerializedName("multisync")
+    @Expose
+    public boolean multisync;
+
+    @SerializedName("current_playlist")
+    @Expose
+    public FPPPlaylist current_playlist;
+
+    @SerializedName("bridging")
+    @Expose
+    public boolean bridging;
+
+    @SerializedName("scheduler")
+    @Expose
+    public FPPScheduler scheduler;
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPCurrentPlaylist.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPCurrentPlaylist.java
new file mode 100644 (file)
index 0000000..3b4a4a3
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link FPPCurrentPlaylist} is responsible for storing
+ * the FPP JSON Current Playlist data.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+public class FPPCurrentPlaylist {
+    @SerializedName("playlistName")
+    @Expose
+    public String playlistName;
+
+    @SerializedName("scheduledStartTimeStr")
+    @Expose
+    public String scheduledStartTimeStr;
+
+    @SerializedName("scheduledEndTimeStr")
+    @Expose
+    public String scheduledEndTimeStr;
+
+    @SerializedName("stopTypeStr")
+    @Expose
+    public String stopTypeStr;
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPNextPlaylist.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPNextPlaylist.java
new file mode 100644 (file)
index 0000000..34c8f8c
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link FPPNextPlaylist} is responsible for storing
+ * the FPP JSON Next Playlist data.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+public class FPPNextPlaylist {
+    /*
+     * "nextPlaylist" :
+     * {
+     * "playlistName" : "No playlist scheduled.",
+     * "scheduledStartTime" : 0,
+     * "scheduledStartTimeStr" : ""
+     * },
+     */
+
+    @SerializedName("playlistName")
+    @Expose
+    public String playlistName;
+
+    @SerializedName("scheduledStartTimeStr")
+    @Expose
+    public String scheduledStartTimeStr;
+
+    @SerializedName("scheduledStartTime")
+    @Expose
+    public int scheduledStartTime;
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPPlaylist.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPPlaylist.java
new file mode 100644 (file)
index 0000000..0a2495b
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link FPPPlaylist} is responsible for storing
+ * the FPP JSON Status data.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+public class FPPPlaylist {
+    /*
+     * 
+     * "current_playlist" :
+     * {
+     * "count" : "0",
+     * "description" : "",
+     * "index" : "0",
+     * "playlist" : "",
+     * "type" : ""
+     * }
+     * 
+     */
+
+    @SerializedName("playlist")
+    @Expose
+    public String playlist;
+
+    @SerializedName("description")
+    @Expose
+    public String description;
+
+    @SerializedName("count")
+    @Expose
+    public int count;
+
+    @SerializedName("index")
+    @Expose
+    public int index;
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPScheduler.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/dto/FPPScheduler.java
new file mode 100644 (file)
index 0000000..783ec83
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link FPPPlaylist} is responsible for storing
+ * the FPP JSON FPPScheduler data.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+public class FPPScheduler {
+    @SerializedName("currentPlaylist")
+    @Expose
+    public FPPCurrentPlaylist currentPlaylist;
+
+    @SerializedName("nextPlaylist")
+    @Expose
+    public FPPNextPlaylist nextPlaylist;
+
+    @SerializedName("enabled")
+    @Expose
+    public int enabled;
+
+    @SerializedName("status")
+    @Expose
+    public String status;
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/handler/FPPPlayerHandler.java b/bundles/org.openhab.binding.mqtt.fpp/src/main/java/org/openhab/binding/mqtt/fpp/internal/handler/FPPPlayerHandler.java
new file mode 100644 (file)
index 0000000..bb89b75
--- /dev/null
@@ -0,0 +1,282 @@
+/**
+ * Copyright (c) 2010-2024 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.mqtt.fpp.internal.handler;
+
+import static org.openhab.binding.mqtt.fpp.internal.FPPBindingConstants.*;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.mqtt.fpp.internal.ConfigOptions;
+import org.openhab.binding.mqtt.fpp.internal.FPPStatus;
+import org.openhab.binding.mqtt.handler.AbstractBrokerHandler;
+import org.openhab.core.io.net.http.HttpUtil;
+import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
+import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
+import org.openhab.core.library.types.IncreaseDecreaseType;
+import org.openhab.core.library.types.NextPreviousType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.library.types.PlayPauseType;
+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.Bridge;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.thing.Thing;
+import org.openhab.core.thing.ThingRegistry;
+import org.openhab.core.thing.ThingStatus;
+import org.openhab.core.thing.ThingStatusDetail;
+import org.openhab.core.thing.ThingStatusInfo;
+import org.openhab.core.thing.binding.BaseThingHandler;
+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.Gson;
+
+/**
+ * The {@link FPPPlayerHandler} is responsible for handling commands of the globes, which are then
+ * sent to one of the bridges to be sent out by MQTT.
+ *
+ * @author Scott Hanson - Initial contribution
+ */
+@NonNullByDefault
+public class FPPPlayerHandler extends BaseThingHandler implements MqttMessageSubscriber {
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+    private @Nullable MqttBrokerConnection connection;
+
+    private String fullStatusTopic = "";
+    private String fullVersionTopic = "";
+    private int lastKnownVolume = 50;
+    private String lastPlaylist = "";
+    private ConfigOptions config = new ConfigOptions();
+
+    private final Gson gson = new Gson();
+
+    public FPPPlayerHandler(Thing thing, ThingRegistry thingRegistry) {
+        super(thing);
+    }
+
+    private void processIncomingState(String messageJSON) {
+        FPPStatus data = gson.fromJson(messageJSON, FPPStatus.class);
+        updateState(CHANNEL_STATUS, new StringType(data.status_name));
+        updateState(CHANNEL_PLAYER, data.status == 1 ? PlayPauseType.PLAY : PlayPauseType.PAUSE);
+        lastKnownVolume = data.volume;
+        updateState(CHANNEL_VOLUME, new PercentType(data.volume));
+        updateState(CHANNEL_MODE, new StringType(data.mode_name));
+        updateState(CHANNEL_CURRENT_SEQUENCE, new StringType(data.current_sequence));
+        updateState(CHANNEL_CURRENT_SONG, new StringType(data.current_song));
+        updateState(CHANNEL_CURRENT_PLAYLIST, new StringType(data.current_playlist.playlist));
+        updateState(CHANNEL_SEC_PLAYED, new QuantityType<>(new BigDecimal(data.seconds_played), Units.SECOND));
+        updateState(CHANNEL_SEC_REMAINING, new QuantityType<>(new BigDecimal(data.seconds_remaining), Units.SECOND));
+        updateState(CHANNEL_UPTIME, new QuantityType<>(new BigDecimal(data.uptimeTotalSeconds), Units.SECOND));
+        updateState(CHANNEL_BRIDGING, OnOffType.from(data.bridging));
+        updateState(CHANNEL_MULTISYNC, OnOffType.from(data.multisync));
+        updateState(CHANNEL_TESTING, data.status_name.equals(TESTING) ? OnOffType.ON : OnOffType.OFF);
+
+        updateState(CHANNEL_SCHEDULER_STATUS, new StringType(data.scheduler.status));
+        updateState(CHANNEL_SCHEDULER_NEXT_PLAYLIST, new StringType(data.scheduler.nextPlaylist.playlistName));
+        updateState(CHANNEL_SCHEDULER_NEXT_PLAYLIST_START,
+                new StringType(data.scheduler.nextPlaylist.scheduledStartTimeStr));
+
+        if (data.scheduler.currentPlaylist != null) {
+            updateState(CHANNEL_SCHEDULER_CURRENT_PLAYLIST,
+                    new StringType(data.scheduler.currentPlaylist.playlistName));
+            updateState(CHANNEL_SCHEDULER_CURRENT_PLAYLIST_START,
+                    new StringType(data.scheduler.currentPlaylist.playlistName));
+            updateState(CHANNEL_SCHEDULER_CURRENT_PLAYLIST_END,
+                    new StringType(data.scheduler.currentPlaylist.playlistName));
+            updateState(CHANNEL_SCHEDULER_CURRENT_PLAYLIST_STOP_TYPE,
+                    new StringType(data.scheduler.currentPlaylist.playlistName));
+        }
+
+        if (!data.current_playlist.playlist.isEmpty()) {
+            lastPlaylist = data.current_playlist.playlist;
+            updateState(CHANNEL_LAST_PLAYLIST, new StringType(lastPlaylist));
+        }
+
+        thing.setProperty(PROPERTY_UUID, data.uuid);
+    }
+
+    @Override
+    public void handleCommand(ChannelUID channelUID, Command command) {
+        if (command instanceof RefreshType) {
+            return;
+        }
+        String channelId = channelUID.getId();
+        if (channelId.equals(CHANNEL_PLAYER)) {
+            if (command == PlayPauseType.PAUSE || command == OnOffType.OFF) {
+                executeGet("/api/playlists/stop");
+            } else if (command == PlayPauseType.PLAY || command == OnOffType.ON) {
+                if (!lastPlaylist.isEmpty()) {
+                    executeGet("/api/playlist/" + lastPlaylist + "/start");
+                }
+            } else if (command == NextPreviousType.NEXT) {
+                executeGet("/api/command/Next Playlist Item");
+            } else if (command == NextPreviousType.PREVIOUS) {
+                executeGet("/api/command/Prev Playlist Item");
+            }
+        }
+        if (channelId.equals(CHANNEL_VOLUME)) {
+            Integer volume = null;
+            if (command instanceof PercentType percentCommand) {
+                volume = percentCommand.intValue();
+            } else if (command == OnOffType.OFF) {
+                volume = 0;
+            } else if (command == OnOffType.ON) {
+                volume = lastKnownVolume;
+            } else if (command == IncreaseDecreaseType.INCREASE) {
+                if (lastKnownVolume < 100) {
+                    lastKnownVolume++;
+                    volume = lastKnownVolume;
+                }
+            } else if (command == IncreaseDecreaseType.DECREASE) {
+                if (lastKnownVolume > 0) {
+                    lastKnownVolume--;
+                    volume = lastKnownVolume;
+                }
+            }
+            if (volume != null) {
+                lastKnownVolume = volume;
+                executePost("/api/system/volume", "{\"volume\":" + lastKnownVolume + "}");
+                updateState(CHANNEL_VOLUME, new PercentType(lastKnownVolume));
+            }
+        }
+        if (channelId.equals(CHANNEL_TESTING)) {
+            if (command == OnOffType.OFF) {
+                executePost("/api/testmode", GetTestMode(0));
+            } else if (command == OnOffType.ON) {
+                executePost("/api/testmode", GetTestMode(1));
+            }
+        }
+    }
+
+    private String GetTestMode(int enable) {
+        return "{\"mode\":\"RGBChase\",\"subMode\":\"RGBChase-RGB\",\"cycleMS\":1000,\"colorPattern\":\"FF000000FF000000FF\",\"enabled\":"
+                + enable + ",\"channelSet\": \"1-1048576\",\"channelSetType\": \"channelRange\"}";
+    }
+
+    @Override
+    public void initialize() {
+        updateStatus(ThingStatus.UNKNOWN);
+        config = getConfigAs(ConfigOptions.class);
+        if (!config.playerMQTTTopic.isEmpty()) {
+            fullStatusTopic = config.playerMQTTTopic + "/" + STATUS_TOPIC;
+            fullVersionTopic = config.playerMQTTTopic + "/" + VERSION_TOPIC;
+            bridgeStatusChanged(getBridgeStatus());
+            updateStatus(ThingStatus.ONLINE);
+        }
+    }
+
+    @Override
+    public void processMessage(String topic, byte[] payload) {
+        String state = new String(payload, StandardCharsets.UTF_8);
+        logger.trace("Received the following new FPP state:{}:{}", topic, state);
+
+        if (topic.endsWith(STATUS_TOPIC)) {
+            processIncomingState(state);
+        } else if (topic.endsWith(VERSION_TOPIC)) {
+            thing.setProperty(PROPERTY_SOFTWARE_VERSION, state);
+            updateStatus(ThingStatus.ONLINE);
+        }
+    }
+
+    public ThingStatusInfo getBridgeStatus() {
+        Bridge b = getBridge();
+        if (b != null) {
+            return b.getStatusInfo();
+        } else {
+            return new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, null);
+        }
+    }
+
+    @Override
+    public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
+        if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
+            connection = null;
+            return;
+        }
+
+        Bridge localBridge = this.getBridge();
+        if (localBridge == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
+                    "Bridge is missing or offline, you need to setup a working MQTT broker first.");
+            return;
+        }
+        ThingHandler handler = localBridge.getHandler();
+        if (handler instanceof AbstractBrokerHandler abh) {
+            final MqttBrokerConnection connection;
+            try {
+                connection = abh.getConnectionAsync().get(5000, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException | ExecutionException | TimeoutException ignored) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED,
+                        "Bridge handler has no valid broker connection!");
+                return;
+            }
+            this.connection = connection;
+            updateStatus(ThingStatus.UNKNOWN);
+            if (!fullStatusTopic.isEmpty()) {
+                connection.subscribe(fullStatusTopic, this);
+                connection.subscribe(fullVersionTopic, this);
+            }
+        }
+        return;
+    }
+
+    private @Nullable String executeGet(String url) {
+        String response = null;
+        try {
+            response = HttpUtil.executeUrl("GET", "http://" + config.playerAddress + url, 5000);
+
+        } catch (IOException e) {
+            logger.warn("Failed HTTP Post", e);
+        }
+        return response;
+    }
+
+    private boolean executePost(String url, String json) {
+        try {
+            Properties header = new Properties();
+            header.put("Accept", "application/json");
+            header.put("Content-Type", "application/json");
+            String response = HttpUtil.executeUrl("POST", "http://" + config.playerAddress + url, header,
+                    new ByteArrayInputStream(json.getBytes()), "application/json", 5000);
+
+            return !response.isEmpty();
+        } catch (IOException e) {
+            logger.warn("Failed HTTP Post", e);
+        }
+        return false;
+    }
+
+    @Override
+    public void dispose() {
+        MqttBrokerConnection localConnection = connection;
+        if (localConnection != null) {
+            localConnection.unsubscribe(fullStatusTopic, this);
+            localConnection.unsubscribe(fullVersionTopic, this);
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/config/config.xml
new file mode 100644 (file)
index 0000000..82c725d
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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:mqtt:player">
+               <parameter name="playerAddress" type="text" required="true">
+                       <context>network-address</context>
+                       <label>Player Address</label>
+                       <description>Player IP Address or Host Name</description>
+               </parameter>
+               <parameter name="playerMQTTTopic" type="text" required="true">
+                       <context>name</context>
+                       <label>MQTT Player Topic</label>
+                       <description>MQTT Player Status Topic</description>
+               </parameter>
+       </config-description>
+</config-description:config-descriptions>
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/i18n/mqtt.properties b/bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/i18n/mqtt.properties
new file mode 100644 (file)
index 0000000..542c765
--- /dev/null
@@ -0,0 +1,56 @@
+# thing types
+
+thing.label.player=FPP Player
+thing.description.player=FPP Player
+
+# thing types config
+
+thing-type.config.mqtt.player.playerAddress.label = Player Address
+thing-type.config.mqtt.player.playerAddress.description = Player IP Address or Host Name
+thing-type.config.mqtt.player.playerMQTTTopic.label = MQTT Player Topic
+thing-type.config.mqtt.player.playerMQTTTopic.description = MQTT Player Status Topic
+
+# channel types
+
+channel-type.mqtt.player.status.label = Status
+channel-type.mqtt.player.status.description = FPP Player Status
+channel-type.mqtt.player.mode.label = Mode
+channel-type.mqtt.player.mode.description = FPP Player Mode
+channel-type.mqtt.player.current-sequence.label = Current Sequence
+channel-type.mqtt.player.current-sequence.description = FPP Current Sequence
+channel-type.mqtt.player.current-song.label = Current Song
+channel-type.mqtt.player.current-song.description = FPP Current Song
+channel-type.mqtt.player.current-playlist.label = Current Playlist
+channel-type.mqtt.player.current-playlist.description = FPP Current Playlist
+channel-type.mqtt.player.seconds-played.label = Seconds Played
+channel-type.mqtt.player.seconds-played.description = FPP Seconds Played
+channel-type.mqtt.player.seconds-remaining.label = Seconds Remaining
+channel-type.mqtt.player.seconds-remaining.description = FPP Seconds Remaining
+channel-type.mqtt.player.uptime.label = Uptime
+channel-type.mqtt.player.uptime.description = FPP System Uptime (time after start)
+channel-type.mqtt.player.player.label = Player
+channel-type.mqtt.player.player.description = FPP Player Control
+channel-type.mqtt.player.volume.label = Volume
+channel-type.mqtt.player.volume.description = FPP Volume of the Output
+channel-type.mqtt.player.bridging-enabled.label = Bridging
+channel-type.mqtt.player.bridging-enabled.description = FPP Recieving Bridge Data
+channel-type.mqtt.player.multisync-enabled.label = Multisync
+channel-type.mqtt.player.multisync-enabled.description = FPP Multisync Mode Enabled
+channel-type.mqtt.player.testing-enabled.label = Testing
+channel-type.mqtt.player.testing-enabled.description = FPP Is In Test Mode
+channel-type.mqtt.player.last-playlist.label = Last Run Playlist
+channel-type.mqtt.player.last-playlist.description = FPP Last Run Playlist
+channel-type.mqtt.player.scheduler-status.label = Scheduler Status
+channel-type.mqtt.player.scheduler-status.description = FPP Scheduler Status
+channel-type.mqtt.player.scheduler-current-playlist.label = Scheduler Current Playlist
+channel-type.mqtt.player.scheduler-current-playlist.description = FPP Scheduler Current Playlist
+channel-type.mqtt.player.scheduler-current-playlist-start.label = Scheduler Current Playlist Start
+channel-type.mqtt.player.scheduler-current-playlist-start.description = FPP Scheduler Current Playlist Start Time
+channel-type.mqtt.player.scheduler-current-playlist-end.label = Scheduler Current Playlist End
+channel-type.mqtt.player.scheduler-current-playlist-end.description = FPP Scheduler Current Playlist End Time
+channel-type.mqtt.player.scheduler-current-playlist-stop-type.label = Scheduler Current Playlist Stop Type
+channel-type.mqtt.player.scheduler-current-playlist-stop-type.description = FPP Scheduler Current Playlist Stop Type
+channel-type.mqtt.player.scheduler-next-playlist.label = Scheduler Next Playlist
+channel-type.mqtt.player.scheduler-next-playlist.description = FPP Scheduler Next Playlist
+channel-type.mqtt.player.scheduler-next-playlist-start.label = Scheduler Next Playlist Start
+channel-type.mqtt.player.scheduler-next-playlist-start.description = FPP Scheduler Next Playlist Start Time
diff --git a/bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mqtt.fpp/src/main/resources/OH-INF/thing/thing-types.xml
new file mode 100644 (file)
index 0000000..9907655
--- /dev/null
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="mqtt"
+       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">
+
+       <thing-type id="player">
+               <supported-bridge-type-refs>
+                       <bridge-type-ref id="broker"/>
+               </supported-bridge-type-refs>
+               <label>FPP Player</label>
+               <description>FPP Player</description>
+               <channels>
+                       <channel id="player" typeId="player"/>
+                       <channel id="status" typeId="status"/>
+                       <channel id="volume" typeId="volume"/>
+                       <channel id="version" typeId="version"/>
+                       <channel id="mode" typeId="mode"/>
+                       <channel id="current-sequence" typeId="current-sequence"/>
+                       <channel id="current-song" typeId="current-song"/>
+                       <channel id="current-playlist" typeId="current-playlist"/>
+                       <channel id="seconds-played" typeId="seconds-played"/>
+                       <channel id="seconds-remaining" typeId="seconds-remaining"/>
+                       <channel id="uptime" typeId="uptime"/>
+                       <channel id="uuid" typeId="uuid"/>
+                       <channel id="bridging-enabled" typeId="bridging-enabled"/>
+                       <channel id="multisync-enabled" typeId="multisync-enabled"/>
+                       <channel id="testing-enabled" typeId="testing-enabled"/>
+                       <channel id="last-playlist" typeId="last-playlist"/>
+                       <channel id="scheduler-status" typeId="scheduler-status"/>
+                       <channel id="scheduler-current-playlist" typeId="scheduler-current-playlist"/>
+                       <channel id="scheduler-current-playlist-start" typeId="scheduler-current-playlist-start"/>
+                       <channel id="scheduler-current-playlist-end" typeId="scheduler-current-playlist-end"/>
+                       <channel id="scheduler-current-playlist-stop-type" typeId="scheduler-current-playlist-stop-type"/>
+                       <channel id="scheduler-next-playlist" typeId="scheduler-next-playlist"/>
+                       <channel id="scheduler-next-playlist-start" typeId="scheduler-next-playlist-start"/>
+               </channels>
+
+               <properties>
+                       <property name="Software Version">unknown</property>
+                       <property name="uuid">unknown</property>
+               </properties>
+
+               <config-description-ref uri="thing-type:mqtt:player"/>
+       </thing-type>
+       <channel-type id="status">
+               <item-type>String</item-type>
+               <label>Status</label>
+               <description>FPP Player Status</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="mode" advanced="true">
+               <item-type>String</item-type>
+               <label>Mode</label>
+               <description>FPP Player Mode</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="current-sequence">
+               <item-type>String</item-type>
+               <label>Current Sequence</label>
+               <description>FPP Current Sequence</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="current-song">
+               <item-type>String</item-type>
+               <label>Current Song</label>
+               <description>FPP Current Song</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="current-playlist">
+               <item-type>String</item-type>
+               <label>Current Playlist</label>
+               <description>FPP Current Playlist</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="seconds-played" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Seconds Played</label>
+               <description>FPP Seconds Played</description>
+               <state readOnly="true" pattern="%.1f sec"/>
+       </channel-type>
+       <channel-type id="seconds-remaining" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Seconds Remaining</label>
+               <description>FPP Seconds Remaining</description>
+               <state readOnly="true" pattern="%.1f sec"/>
+       </channel-type>
+       <channel-type id="uptime" advanced="true">
+               <item-type>Number:Time</item-type>
+               <label>Uptime</label>
+               <description>FPP System Uptime (time after start)</description>
+               <state readOnly="true" pattern="%.1f sec"/>
+       </channel-type>
+       <channel-type id="player">
+               <item-type>Player</item-type>
+               <label>Player</label>
+               <description>FPP Player Control</description>
+       </channel-type>
+       <channel-type id="volume">
+               <item-type>Dimmer</item-type>
+               <label>Volume</label>
+               <description>FPP Volume of the Output</description>
+       </channel-type>
+       <channel-type id="bridging-enabled" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Bridging</label>
+               <description>FPP Recieving Bridge Data</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="multisync-enabled" advanced="true">
+               <item-type>Switch</item-type>
+               <label>Multisync</label>
+               <description>FPP Multisync Mode Enabled</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="testing-enabled">
+               <item-type>Switch</item-type>
+               <label>Testing</label>
+               <description>FPP Is In Test Mode</description>
+       </channel-type>
+       <channel-type id="last-playlist" advanced="true">
+               <item-type>String</item-type>
+               <label>Last Run Playlist</label>
+               <description>FPP Last Run Playlist</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-status" advanced="true">
+               <item-type>String</item-type>
+               <label>Scheduler Status</label>
+               <description>FPP Scheduler Status</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-current-playlist">
+               <item-type>String</item-type>
+               <label>Scheduler Current Playlist</label>
+               <description>FPP Scheduler Current Playlist</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-current-playlist-start" advanced="true">
+               <item-type>String</item-type>
+               <label>Scheduler Current Playlist Start</label>
+               <description>FPP Scheduler Current Playlist Start Time</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-current-playlist-end" advanced="true">
+               <item-type>String</item-type>
+               <label>Scheduler Current Playlist End</label>
+               <description>FPP Scheduler Current Playlist End Time</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-current-playlist-stop-type" advanced="true">
+               <item-type>String</item-type>
+               <label>Scheduler Current Playlist Stop Type</label>
+               <description>FPP Scheduler Current Playlist Stop Type</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-next-playlist" advanced="true">
+               <item-type>String</item-type>
+               <label>Scheduler Next Playlist</label>
+               <description>FPP Scheduler Next Playlist</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="scheduler-next-playlist-start" advanced="true">
+               <item-type>String</item-type>
+               <label>Scheduler Next Playlist Start</label>
+               <description>FPP Scheduler Next Playlist Start Time</description>
+               <state readOnly="true"/>
+       </channel-type>
+</thing:thing-descriptions>
index b3a32868783738994fe12d15efb9d06c94ed46e3..94b766445216a4936e379b9daf44a696b5344a5f 100644 (file)
     <module>org.openhab.binding.mpd</module>
     <module>org.openhab.binding.mqtt</module>
     <module>org.openhab.binding.mqtt.espmilighthub</module>
+    <module>org.openhab.binding.mqtt.fpp</module>
     <module>org.openhab.binding.mqtt.generic</module>
     <module>org.openhab.binding.mqtt.homeassistant</module>
     <module>org.openhab.binding.mqtt.homie</module>
index 383959548d486512cba3319c20b0e281a0f984f0..9b241a74a7056a95b444f63f0b98568aa0d3abf6 100644 (file)
@@ -28,6 +28,7 @@
                <bundle dependency="true">mvn:ch.obermuhlner/big-math/2.3.2</bundle>
                <bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version}</bundle>
                <bundle start-level="81">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.espmilighthub/${project.version}</bundle>
+               <bundle start-level="81">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.fpp/${project.version}</bundle>
                <bundle start-level="81">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.generic/${project.version}</bundle>
                <bundle start-level="82">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.homeassistant/${project.version}</bundle>
                <bundle start-level="82">mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.homie/${project.version}</bundle>