Created
February 17, 2023 05:27
-
-
Save dangmai/9fd46fac44512b8f9bbea24758d18f25 to your computer and use it in GitHub Desktop.
IOTLink Machine Hubitat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import groovy.json.JsonOutput | |
public static String rootTopic() { return "hubitat" } | |
metadata { | |
definition (name: "IOT Link Machine", namespace: "iotlink", author: "Dang Mai") { | |
attribute "idleTime", "number" | |
} | |
capability "Actuator" | |
preferences { | |
input( | |
name: "brokerIp", | |
type: "string", | |
title: "MQTT Broker IP Address", | |
description: "e.g. 192.168.1.200", | |
required: true, | |
displayDuringSetup: true | |
) | |
input( | |
name: "brokerPort", | |
type: "string", | |
title: "MQTT Broker Port", | |
description: "e.g. 1883", | |
required: true, | |
displayDuringSetup: true | |
) | |
input( | |
name: "brokerUser", | |
type: "string", | |
title: "MQTT Broker Username", | |
description: "e.g. mqtt_user", | |
required: false, | |
displayDuringSetup: true | |
) | |
input( | |
name: "brokerPassword", | |
type: "password", | |
title: "MQTT Broker Password", | |
description: "e.g. ^L85er1Z7g&%2En!", | |
required: false, | |
displayDuringSetup: true | |
) | |
input( | |
name: "domain", | |
type: "string", | |
title: "The domain that the computer belongs to", | |
description: "e.g. workgroup", | |
required: false, | |
default: "workgroup", | |
displayDuringSetup: true | |
) | |
input( | |
name: "machineName", | |
type: "string", | |
title: "Name of machine in the domain", | |
description: "e.g. computer-name", | |
required: true, | |
displayDuringSetup: true | |
) | |
input( | |
name: "debugLogging", | |
type: "bool", | |
title: "Enable debug logging", | |
required: false, | |
default: false | |
) | |
} | |
command "shutdown" | |
} | |
void initialize() { | |
debug("Initializing driver...") | |
try { | |
interfaces.mqtt.connect( | |
getBrokerUri(), | |
"hubitat_${getHubId()}", | |
settings?.brokerUser, | |
settings?.brokerPassword, | |
lastWillTopic: "${getDriverTopicPrefix()}LWT", | |
lastWillQos: 0, | |
lastWillMessage: "offline", | |
lastWillRetain: true) | |
// delay for connection | |
pauseExecution(1000) | |
subscribe("windows-monitor/stats/system/idle-time") | |
unschedule("checkConnection") | |
schedule("0 */1 * ? * *", "checkConnection") | |
} catch(Exception e) { | |
error("[d:initialize] ${e}") | |
} | |
} | |
void installed() { | |
debug("installed") | |
disconnect() | |
connect() | |
} | |
void updated() { | |
debug("updated") | |
disconnect() | |
connect() | |
} | |
void checkConnection() { | |
if (notMqttConnected()) { | |
debug("not connected, attempting reconnect") | |
connect() | |
} | |
} | |
// ======================================================== | |
// MQTT COMMANDS | |
// ======================================================== | |
void shutdown() { | |
debug("Shutting down") | |
publish("commands/shutdown", "") | |
} | |
def publish(topic, payload) { | |
publishMachineMqtt(topic, payload) | |
} | |
def subscribe(topic) { | |
if (notMqttConnected()) { | |
connect() | |
} | |
debug("[d:subscribe] full topic: ${getTopic(topic)}") | |
interfaces.mqtt.subscribe("${getTopic(topic)}") | |
} | |
def unsubscribe(topic) { | |
if (notMqttConnected()) { | |
connect() | |
} | |
debug("[d:unsubscribe] full topic: ${getTopic(topic)}") | |
interfaces.mqtt.unsubscribe("${getTopic(topic)}") | |
} | |
def connect() { | |
initialize() | |
connected() | |
} | |
def disconnect() { | |
debug("disconnect") | |
try { | |
interfaces.mqtt.disconnect() | |
disconnected() | |
} catch(e) { | |
warn("Disconnection from broker failed", ${e.message}) | |
if (interfaces.mqtt.isConnected()) connected() | |
} | |
} | |
// ======================================================== | |
// MQTT METHODS | |
// ======================================================== | |
// Parse incoming message from the MQTT broker | |
def parse(String event) { | |
def message = interfaces.mqtt.parseMessage(event) | |
// iotlink/workgroup/isengard/windows-monitor/stats/system/idle-time | |
def (prefix, domain, machine, monitor, stats, system, name) = message.topic.tokenize( '/' ) | |
// ignore all msgs that aren't commands | |
//if (cmd != 'cmd') return | |
if (name != 'idle-time') return | |
debug("[d:parse] Received MQTT message: ${message}") | |
sendEvent(name: "idleTime", value: message.payload) | |
} | |
def mqttClientStatus(status) { | |
debug("[d:mqttClientStatus] status: ${status}") | |
} | |
def publishMachineMqtt(topic, payload, qos = 0, retained = false) { | |
if (notMqttConnected()) { | |
debug("[d:publishMachineMqtt] not connected") | |
initialize() | |
} | |
def pubTopic = "${getTopic(topic)}" | |
try { | |
interfaces.mqtt.publish("${pubTopic}", payload, qos, retained) | |
debug("[d:publishMachineMqtt] topic: ${pubTopic} payload: ${payload}") | |
} catch (Exception e) { | |
error("[d:publishMachineMqtt] Unable to publish message: ${e}") | |
} | |
} | |
def publishDeviceMqtt(topic, payload, qos = 0, retained = false) { | |
if (notMqttConnected()) { | |
debug("[d:publishDeviceMqtt] not connected") | |
initialize() | |
} | |
def pubTopic = "${getDriverTopicPrefix()}${topic}" | |
try { | |
interfaces.mqtt.publish("${pubTopic}", payload, qos, retained) | |
debug("[d:publishDeviceMqtt] topic: ${pubTopic} payload: ${payload}") | |
} catch (Exception e) { | |
error("[d:publishDeviceMqtt] Unable to publish message: ${e}") | |
} | |
} | |
// ======================================================== | |
// ANNOUNCEMENTS | |
// ======================================================== | |
def connected() { | |
debug("[d:connected] Connected to broker") | |
sendEvent (name: "connectionState", value: "connected") | |
announceLwtStatus("online") | |
} | |
def disconnected() { | |
debug("[d:disconnected] Disconnected from broker") | |
sendEvent (name: "connectionState", value: "disconnected") | |
announceLwtStatus("offline") | |
} | |
def announceLwtStatus(String status) { | |
publishDeviceMqtt("LWT", status) | |
publishDeviceMqtt("FW", "${location.hub.firmwareVersionString}") | |
publishDeviceMqtt("IP", "${location.hub.localIP}") | |
publishDeviceMqtt("UPTIME", "${location.hub.uptime}") | |
} | |
// ======================================================== | |
// HELPERS | |
// ======================================================== | |
def getBrokerUri() { | |
return "tcp://${settings?.brokerIp}:${settings?.brokerPort}" | |
} | |
def normalize(name) { | |
return name.replaceAll("[^a-zA-Z0-9]+","-").toLowerCase() | |
} | |
def getHubId() { | |
def hub = location.hubs[0] | |
def hubNameNormalized = normalize(hub.name) | |
return "${hubNameNormalized}-${hub.hardwareID}".toLowerCase() | |
} | |
def getDriverTopicPrefix() { | |
return "${rootTopic()}/${getHubId()}/" | |
} | |
def getMachineTopicPrefix() { | |
return "iotlink/${settings?.domain}/${settings?.machineName}" | |
} | |
def getTopic(topic) { | |
return "${getMachineTopicPrefix()}/${topic}" | |
} | |
def mqttConnected() { | |
return interfaces.mqtt.isConnected() | |
} | |
def notMqttConnected() { | |
return !mqttConnected() | |
} | |
// ======================================================== | |
// LOGGING | |
// ======================================================== | |
def debug(msg) { | |
if (debugLogging) { | |
log.debug msg | |
} | |
} | |
def info(msg) { | |
log.info msg | |
} | |
def warn(msg) { | |
log.warn msg | |
} | |
def error(msg) { | |
log.error msg | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment