## Channels
-| Channel | Type | Read/Write | Description |
-|-------------------------|--------|------------|------------------------------------------------------------|
-| domains-being-blocked | Number | RO | The total number of domains currently being blocked. |
-| dns-queries-today | Number | RO | The count of DNS queries made today. |
-| ads-blocked-today | Number | RO | The number of ads blocked today. |
-| ads-percentage-today | Number | RO | The percentage of ads blocked today. |
-| unique-domains | Number | RO | The count of unique domains queried. |
-| queries-forwarded | Number | RO | The number of queries forwarded to an external DNS server. |
-| queries-cached | Number | RO | The number of queries served from the cache. |
-| clients-ever-seen | Number | RO | The total number of unique clients ever seen. |
-| unique-clients | Number | RO | The current count of unique clients. |
-| dns-queries-all-types | Number | RO | The total number of DNS queries of all types. |
-| reply-unknown | Number | RO | DNS replies with an unknown status. |
-| reply-nodata | Number | RO | DNS replies indicating no data. |
-| reply-nxdomain | Number | RO | DNS replies indicating non-existent domain. |
-| reply-cname | Number | RO | DNS replies with a CNAME record. |
-| reply-ip | Number | RO | DNS replies with an IP address. |
-| reply-domain | Number | RO | DNS replies with a domain name. |
-| reply-rrname | Number | RO | DNS replies with a resource record name. |
-| reply-servfail | Number | RO | DNS replies indicating a server failure. |
-| reply-refused | Number | RO | DNS replies indicating refusal. |
-| reply-notimp | Number | RO | DNS replies indicating not implemented. |
-| reply-other | Number | RO | DNS replies with other statuses. |
-| reply-dnssec | Number | RO | DNS replies with DNSSEC information. |
-| reply-none | Number | RO | DNS replies with no data. |
-| reply-blob | Number | RO | DNS replies with a BLOB (binary large object). |
-| dns-queries-all-replies | Number | RO | The total number of DNS queries with all reply types. |
-| privacy-level | Number | RO | The privacy level setting. |
-| enabled | Switch | RO | The current status of blocking |
-| disable-enable | String | RW | Is blocking enabled/disabled |
+| Channel | Type | Read/Write | Description |
+|-------------------------|----------|------------|------------------------------------------------------------|
+| domains-being-blocked | Number | RO | The total number of domains currently being blocked. |
+| dns-queries-today | Number | RO | The count of DNS queries made today. |
+| ads-blocked-today | Number | RO | The number of ads blocked today. |
+| ads-percentage-today | Number | RO | The percentage of ads blocked today. |
+| unique-domains | Number | RO | The count of unique domains queried. |
+| queries-forwarded | Number | RO | The number of queries forwarded to an external DNS server. |
+| queries-cached | Number | RO | The number of queries served from the cache. |
+| clients-ever-seen | Number | RO | The total number of unique clients ever seen. |
+| unique-clients | Number | RO | The current count of unique clients. |
+| dns-queries-all-types | Number | RO | The total number of DNS queries of all types. |
+| reply-unknown | Number | RO | DNS replies with an unknown status. |
+| reply-nodata | Number | RO | DNS replies indicating no data. |
+| reply-nxdomain | Number | RO | DNS replies indicating non-existent domain. |
+| reply-cname | Number | RO | DNS replies with a CNAME record. |
+| reply-ip | Number | RO | DNS replies with an IP address. |
+| reply-domain | Number | RO | DNS replies with a domain name. |
+| reply-rrname | Number | RO | DNS replies with a resource record name. |
+| reply-servfail | Number | RO | DNS replies indicating a server failure. |
+| reply-refused | Number | RO | DNS replies indicating refusal. |
+| reply-notimp | Number | RO | DNS replies indicating not implemented. |
+| reply-other | Number | RO | DNS replies with other statuses. |
+| reply-dnssec | Number | RO | DNS replies with DNSSEC information. |
+| reply-none | Number | RO | DNS replies with no data. |
+| reply-blob | Number | RO | DNS replies with a BLOB (binary large object). |
+| dns-queries-all-replies | Number | RO | The total number of DNS queries with all reply types. |
+| privacy-level | Number | RO | The privacy level setting. |
+| enabled | Switch | RO | The current status of blocking |
+| disable-enable | String | RW | Is blocking enabled/disabled |
+| gravity-last-update | DateTime | RO | Last update of gravity |
+| gravity-file-exists | DateTime | RO | Does gravity file exists |
## Full Example
public static final String PRIVACY_LEVEL_CHANNEL = "privacy-level";
public static final String ENABLED_CHANNEL = "enabled";
public static final String DISABLE_ENABLE_CHANNEL = "disable-enable";
+ public static final String GRAVITY_FILE_EXISTS = "gravity-file-exists";
+ public static final String GRAVITY_LAST_UPDATE = "gravity-last-update";
public static enum DisableEnable {
DISABLE,
package org.openhab.binding.pihole.internal;
import static java.util.concurrent.TimeUnit.*;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.ADS_BLOCKED_TODAY_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.ADS_PERCENTAGE_TODAY_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.CLIENTS_EVER_SEEN_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DISABLE_ENABLE_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DNS_QUERIES_ALL_REPLIES_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DNS_QUERIES_ALL_TYPES_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DNS_QUERIES_TODAY_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DOMAINS_BEING_BLOCKED_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DisableEnable;
+import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.*;
import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.DisableEnable.ENABLE;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.ENABLED_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.PRIVACY_LEVEL_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.QUERIES_CACHED_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.QUERIES_FORWARDED_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_BLOB_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_CNAME_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_DNSSEC_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_DOMAIN_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_IP_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_NODATA_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_NONE_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_NOTIMP_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_NXDOMAIN_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_OTHER_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_REFUSED_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_RRNAME_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_SERVFAIL_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.REPLY_UNKNOWN_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.UNIQUE_CLIENTS_CHANNEL;
-import static org.openhab.binding.pihole.internal.PiHoleBindingConstants.Channels.UNIQUE_DOMAINS_CHANNEL;
import static org.openhab.core.library.unit.Units.PERCENT;
import static org.openhab.core.thing.ThingStatus.OFFLINE;
import static org.openhab.core.thing.ThingStatus.ONLINE;
import java.math.BigDecimal;
import java.net.URI;
import java.net.URISyntaxException;
+import java.time.Instant;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import org.openhab.binding.pihole.internal.rest.AdminService;
import org.openhab.binding.pihole.internal.rest.JettyAdminService;
import org.openhab.binding.pihole.internal.rest.model.DnsStatistics;
+import org.openhab.core.i18n.TimeZoneProvider;
+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;
private static final int HTTP_DELAY_SECONDS = 1;
private final Logger logger = LoggerFactory.getLogger(PiHoleHandler.class);
private final Object lock = new Object();
+ private final TimeZoneProvider timeZoneProvider;
private final HttpClient httpClient;
private @Nullable AdminService adminService;
private @Nullable DnsStatistics dnsStatistics;
private @Nullable ScheduledFuture<?> scheduledFuture;
- public PiHoleHandler(Thing thing, HttpClient httpClient) {
+ public PiHoleHandler(Thing thing, TimeZoneProvider timeZoneProvider, HttpClient httpClient) {
super(thing);
+ this.timeZoneProvider = timeZoneProvider;
this.httpClient = httpClient;
}
if (localDnsStatistics.enabled()) {
updateState(DISABLE_ENABLE_CHANNEL, new StringType(ENABLE.toString()));
}
+ var gravityLastUpdated = localDnsStatistics.gravityLastUpdated();
+ if (gravityLastUpdated != null) {
+ var absolute = gravityLastUpdated.absolute();
+ if (absolute != null) {
+ var instant = Instant.ofEpochSecond(absolute);
+ var zonedDateTime = instant.atZone(timeZoneProvider.getTimeZone());
+ updateState(GRAVITY_LAST_UPDATE, new DateTimeType(zonedDateTime));
+ }
+ var fileExists = gravityLastUpdated.fileExists();
+ if (fileExists != null) {
+ updateState(GRAVITY_FILE_EXISTS, OnOffType.from(fileExists));
+ }
+ }
}
private void updateDecimalState(String channelID, @Nullable Integer value) {
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
+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;
public class PiHoleHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(PI_HOLE_TYPE);
+ private final TimeZoneProvider timeZoneProvider;
private final HttpClientFactory httpClientFactory;
@Activate
- public PiHoleHandlerFactory(@Reference HttpClientFactory httpClientFactory) {
+ public PiHoleHandlerFactory(@Reference TimeZoneProvider timeZoneProvider,
+ @Reference HttpClientFactory httpClientFactory) {
+ this.timeZoneProvider = timeZoneProvider;
this.httpClientFactory = httpClientFactory;
}
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (PI_HOLE_TYPE.equals(thingTypeUID)) {
- return new PiHoleHandler(thing, httpClientFactory.getCommonHttpClient());
+ return new PiHoleHandler(thing, timeZoneProvider, httpClientFactory.getCommonHttpClient());
}
return null;
<channel id="enabled" typeId="enabled-channel"/>
<channel id="disable-enable" typeId="disable-enable-channel"/>
</channels>
+ <properties>
+ <property name="thingTypeVersion">1</property>
+ </properties>
<config-description>
<parameter name="hostname" type="text" required="true">
</options>
</command>
</channel-type>
+ <channel-type id="gravity-file-exists-channel">
+ <item-type>Switch</item-type>
+ <label>Gravity File Exists</label>
+ <state readOnly="true"/>
+ </channel-type>
+ <channel-type id="gravity-last-update-channel">
+ <item-type>DateTime</item-type>
+ <label>Gravity Last Update</label>
+ <category>time</category>
+ <state readOnly="true"/>
+ </channel-type>
</thing:thing-descriptions>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<update:update-descriptions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:update="https://openhab.org/schemas/update-description/v1.0.0"
+ xsi:schemaLocation="https://openhab.org/schemas/update-description/v1.0.0 https://openhab.org/schemas/update-description-1.0.0.xsd">
+
+ <thing-type uid="pihole:server">
+ <instruction-set targetVersion="1">
+ <add-channel id="gravity-file-exists">
+ <type>pihole:gravity-file-exists-channel</type>
+ </add-channel>
+ <add-channel id="gravity-last-update">
+ <type>pihole:gravity-last-update-channel</type>
+ </add-channel>
+ </instruction-set>
+ </thing-type>
+</update:update-descriptions>