This repository has been archived by the owner on Oct 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 193
/
UPnP TV Discovery.groovy
166 lines (159 loc) · 5.57 KB
/
UPnP TV Discovery.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* ===== HUBITAT INTEGRATION VERSION =====================================================
UpNp Media Player and MainTVAgent Discovery
This is a test application to discover UPnP devices related to Media Player
as well as Samsung devices with MainTvAgent2. It does a discovery process
and then identifies the devices by name, IP, and Port into two state:
Media Player and MainTvAgent2
===== HUBITAT INTEGRATION VERSION =======================================================*/
//import org.json.JSONObject
def appVersion() { return "TEST" }
def appName() { return "UPnP TV Test" }
definition(
name: "UPnP Identification",
namespace: "davegut",
author: "Dave Gutheinz",
description: "Application to identify Media Players.",
category: "Convenience",
iconUrl: "",
iconX2Url: "",
singleInstance: true,
importUrl: ""
)
preferences {
page(name: "mainPage")
page(name: "discovery")
}
// ===== Page Definitions =====
def mainPage() {
logInfo("mainPage")
setInitialStates()
ssdpSubscribe()
def page1 = "0. Turn on devices you wish to check for at least 1 minute.\n"
page1 += "1. Press 'Next' to find UPnP devices.\n"
page1 += "2. When done, open the App info page (gear icon), Application States.\n"
page1 += " I need the <b>devices</b> data from the states section.\n"
return dynamicPage(
name: "mainPage",
title: "UPnP Identification",
nextPage: "discovery",
install: false,
uninstall: true){
section(page1) {}
}
}
def discovery() {
logInfo("discovery")
def devices = state.devices
def devList = ""
devices.each {
devList += "${it}\n\n"
}
ssdpDiscover()
def text2 = "<b>Allow at least two minutes to discover your devices</b>\n\r\n\r"
return dynamicPage(
name: "discovery",
title: "Device Discovery",
nextPage: "",
refreshInterval: 10,
install: true,
uninstall: true){
section("<b>Allow at least 2 minutes for discovery</b>") {
paragraph "<b>UPnP Devices Discovery Data</b>"
paragraph "<textarea rows=30 cols=50 readonly='true'>${devList}</textarea>"
}
}
}
// ===== Start up Functions =====
def setInitialStates() {
state.ssdpDevices = [:]
state.devices = [:]
}
def installed() { initialize() }
def updated() { initialize() }
def initialize() { unschedule() }
// ===== Device Discovery =====
void ssdpSubscribe() {
logInfo("ssdpSubscribe")
unsubscribe()
subscribe(location, "ssdpTerm.urn:schemas-upnp-org:device:MediaRenderer:1", ssdpHandler)
subscribe(location, "ssdpTerm.urn:samsung.com:device:MainTVServer2:1", ssdpHandler)
}
void ssdpDiscover() {
logInfo("ssdpDiscover")
sendHubCommand(new hubitat.device.HubAction("lan discovery urn:schemas-upnp-org:device:MediaRenderer:1", hubitat.device.Protocol.LAN))
pauseExecution(1000)
sendHubCommand(new hubitat.device.HubAction("lan discovery urn:samsung.com:device:MainTVServer2:1", hubitat.device.Protocol.LAN))
pauseExecution(1000)
getDevData()
}
def ssdpHandler(evt) {
def parsedEvent = parseLanMessage(evt.description)
def ip = convertHexToIP(parsedEvent.networkAddress)
def path = parsedEvent.ssdpPath
def port = convertHexToInt(parsedEvent.deviceAddress)
def key = "${ip}:${path}${port}"
def devices = state.devices
device = [:]
device["dni"] = parsedEvent.mac
device["ip"] = ip
devices << ["${parsedEvent.mac}": device]
logInfo("ssdpHandler: found device dni = ${parsedEvent.mac}")
def ssdpDevices = state.ssdpDevices
ssdpDevice = [:]
ssdpDevice["ip"] = ip
ssdpDevice["port"] = port
ssdpDevice["path"] = path
ssdpDevices << ["${key}": ssdpDevice]
}
def getDevData() {
def ssdpDevices = state.ssdpDevices
ssdpDevices.each {
logInfo("getDeviceData: path = ${it.value.ip}:${it.value.port}${it.value.path}")
sendCmd(it.value.path, it.value.ip, it.value.port, "addDeviceData")
pauseExecution(300)
}
}
void addDeviceData(resp) {
def devices = state.devices
def device = devices.find { it.key == resp.mac }
if (device) {
def type = resp.xml.device.deviceType
def port = convertHexToInt(resp.port)
device.value << [manufacturer: "${resp.xml.device.manufacturer.text()}"]
def services = resp.xml.device.serviceList.service
services.each {
if (it.serviceType.text() == "urn:samsung.com:service:MainTVAgent2:1") {
device.value << [tvPort: "${port}",
tvUrn: "${it.serviceType.text()}",
tvPath: "${it.controlURL.text()}"]
} else if (it.serviceType.text() == "urn:schemas-upnp-org:service:AVTransport:1") {
device.value << [avPort: "${port}",
avUrn: "${it.serviceType.text()}",
avPath: "${it.controlURL.text()}"]
} else if (it.serviceType.text() == "urn:schemas-upnp-org:service:RenderingControl:1") {
device.value << [rcPort: "${port}",
rcUrn: "${it.serviceType.text()}",
rcPath: "${it.controlURL.text()}"]
}
}
}
logInfo("addDeviceData: found data for device ${resp.mac}")
}
private sendCmd(command, deviceIP, devicePort, action){
def host = "${deviceIP}:${devicePort}"
sendHubCommand(new hubitat.device.HubAction("""GET ${command} HTTP/1.1\r\nHOST: ${host}\r\n\r\n""",
hubitat.device.Protocol.LAN, host, [callback: action]))
}
def logWarn(message) {
log.warn "${appName()} ${appVersion()}: ${message}"
}
def logInfo(message) {
log.info "${appName()} ${appVersion()}: ${message}"
}
// ----- Utility Functions SHOULD DISAPPEAR-----
private Integer convertHexToInt(hex) {
Integer.parseInt(hex,16)
}
private String convertHexToIP(hex) {
[convertHexToInt(hex[0..1]),convertHexToInt(hex[2..3]),convertHexToInt(hex[4..5]),convertHexToInt(hex[6..7])].join(".")
}