mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-11 13:21:51 +00:00
220 lines
5.9 KiB
Groovy
220 lines
5.9 KiB
Groovy
/**
|
|
* ObyThing Music Connect
|
|
*
|
|
* Copyright 2015 obycode
|
|
*
|
|
*/
|
|
definition(
|
|
name: "obything Connect",
|
|
namespace: "com.obycode",
|
|
author: "obycode",
|
|
description: "Smart home, smart Mac. With obything.",
|
|
category: "Fun & Social",
|
|
iconUrl: "http://obything.obycode.com/icons/icon60.png",
|
|
iconX2Url: "http://obything.obycode.com/icons/icon120.png",
|
|
iconX3Url: "http://obything.obycode.com/icons/icon120.png",
|
|
oauth: [displayName: "obything", displayLink: "http://obything.obycode.com"])
|
|
|
|
|
|
preferences {
|
|
section("Smart home, smart Mac. With obything.") {
|
|
app(name: "childApps", appName: "obything Notify with Sound", namespace: "com.obycode", title: "Notify with Sound", multiple: true)
|
|
app(name: "childApps", appName: "obything Music Control", namespace: "com.obycode", title: "Music Control", multiple: true)
|
|
app(name: "childApps", appName: "obything Trigger Playlist", namespace: "com.obycode", title: "Trigger Playlists", multiple: true)
|
|
app(name: "childApps", appName: "obything Weather Forecast", namespace: "com.obycode", title: "Weather Forecast", multiple: true)
|
|
}
|
|
}
|
|
|
|
mappings {
|
|
path("/setup") {
|
|
action: [
|
|
POST: "setup",
|
|
]
|
|
}
|
|
path("/:uuid/:kind") {
|
|
action: [
|
|
POST: "createChild",
|
|
PUT: "updateChild",
|
|
]
|
|
}
|
|
}
|
|
|
|
def installed() {
|
|
log.debug "Installed"
|
|
}
|
|
|
|
def updated() {
|
|
log.debug "Updated"
|
|
|
|
unsubscribe()
|
|
}
|
|
|
|
def uninstalled() {
|
|
logout()
|
|
}
|
|
|
|
def logout() {
|
|
revokeAccessToken()
|
|
}
|
|
|
|
// mapping handlers
|
|
|
|
// /setup POST
|
|
def setup() {
|
|
def ip = request.JSON?.ip
|
|
if (ip == null) {
|
|
return httpError(400, "IP not specified")
|
|
}
|
|
def port = request.JSON?.port
|
|
if (port == null) {
|
|
return httpError(400, "Port not specified")
|
|
}
|
|
def name = request.JSON?.name
|
|
if (name == null) {
|
|
return httpError(400, "Name not specified")
|
|
}
|
|
def uuid = request.JSON?.uuid
|
|
if (uuid == null) {
|
|
return httpError(400, "UUID not specified")
|
|
}
|
|
|
|
// If machines is not initialized yet, set it up
|
|
if (state.machines == null) {
|
|
state.machines = [:]
|
|
}
|
|
|
|
// If this machine has already been initialized, just update it
|
|
if (state.machines[uuid]) {
|
|
state.machines[uuid]["ip"] = ip
|
|
state.machines[uuid]["port"] = port
|
|
state.machines[uuid]["name"] = name
|
|
log.debug "Updated machine"
|
|
|
|
def dead = []
|
|
// Update the child devices
|
|
def newHexIP = convertIPtoHex(ip)
|
|
state.machines[uuid]["children"].keySet().each {
|
|
def ids = state.machines[uuid]["children"][it]
|
|
def child = getChildDevice(ids.dni)
|
|
if (!child) {
|
|
dead.add(it)
|
|
}
|
|
else {
|
|
// Only change the IP; the label could've been manually changed and I'm
|
|
// not sure how to handle the port changing (its not allowed now anyway).
|
|
def oldHexPort = child.deviceNetworkId.split(':')[1]
|
|
def newDNI = "$newHexIP:$oldHexPort"
|
|
child.deviceNetworkId = newDNI
|
|
state.machines[uuid]["children"][it]["dni"] = newDNI
|
|
}
|
|
}
|
|
dead.each {
|
|
state.machines[uuid]["children"].remove(it)
|
|
}
|
|
}
|
|
// Otherwise, just create a new machine
|
|
else {
|
|
def machine = [ip:ip, port:port, name:name, children:[:]]
|
|
state.machines[uuid] = machine
|
|
log.debug "Added new machine"
|
|
}
|
|
|
|
sendCommand(state.machines[uuid], "/ping")
|
|
}
|
|
|
|
private removeChildDevices(delete) {
|
|
delete.each {
|
|
deleteChildDevice(it.deviceNetworkId)
|
|
}
|
|
}
|
|
|
|
// /:uuid/:kind POST
|
|
def createChild() {
|
|
// Constants for the port offsets
|
|
final int iTunesService = 1
|
|
final int pandoraService = 2
|
|
final int spotifyService = 3
|
|
|
|
def machine = state.machines[params.uuid]
|
|
if (machine == null) {
|
|
return httpError(404, "Machine not found")
|
|
}
|
|
|
|
def childName = machine["name"]
|
|
def portNum = machine["port"].toInteger()
|
|
switch (params.kind) {
|
|
case "itunes":
|
|
childName = childName + " iTunes"
|
|
portNum += iTunesService
|
|
break
|
|
case "pandora":
|
|
childName = childName + " Pandora"
|
|
portNum += pandoraService
|
|
break
|
|
case "spotify":
|
|
childName = childName + " Spotify"
|
|
portNum += spotifyService
|
|
break
|
|
default:
|
|
return httpError(400, "Unknown or unspecified device type")
|
|
}
|
|
|
|
def hexIP = convertIPtoHex(machine["ip"])
|
|
def hexPort = convertPortToHex(portNum.toString())
|
|
def childId = "$hexIP:$hexPort"
|
|
|
|
// If this child already exists, re-associate with it
|
|
def existing = getChildDevice(childId)
|
|
if (existing) {
|
|
log.debug "Found existing device: $existing"
|
|
state.machines[params.uuid]["children"][params.kind] = [id:existing.id, dni:childId]
|
|
}
|
|
// otherwise, create it
|
|
else {
|
|
def d = addChildDevice("com.obycode", "obything Music Player", childId, location.hubs[0].id, [name:"obything Music Player", label:childName, completedSetup:true])
|
|
log.debug "Created child device: $d"
|
|
state.machines[params.uuid]["children"][params.kind] = [id:d.id, dni:d.deviceNetworkId]
|
|
}
|
|
|
|
return [dni:childId]
|
|
}
|
|
|
|
// /:uuid/:kind PUT
|
|
def updateChild() {
|
|
def machine = state.machines[params.uuid]
|
|
if (machine == null) {
|
|
return httpError(404, "Machine not found")
|
|
}
|
|
|
|
def child = machine["children"][params.kind]
|
|
if (child == null) {
|
|
return httpError(404, "Device not found")
|
|
}
|
|
|
|
def device = getChildDevice(child.dni)
|
|
if (device == null) {
|
|
return httpError(404, "Device not found")
|
|
}
|
|
|
|
device.update(request.JSON)
|
|
}
|
|
|
|
private String convertIPtoHex(ipAddress) {
|
|
String hex = ipAddress.tokenize( '.' ).collect { String.format( '%02X', it.toInteger() ) }.join()
|
|
return hex
|
|
|
|
}
|
|
|
|
private String convertPortToHex(port) {
|
|
String hexport = port.toString().format( '%04X', port.toInteger() )
|
|
return hexport
|
|
}
|
|
|
|
private void sendCommand(machine, path, command = null) {
|
|
def fullPath = path
|
|
if (command) {
|
|
fullPath = fullPath + "?" + command
|
|
}
|
|
sendHubCommand(new physicalgraph.device.HubAction("GET " + fullPath + """ HTTP/1.1\r\nHOST: """ + machine["ip"] + ":" + machine["port"] + """\r\n\r\n""", physicalgraph.device.Protocol.LAN))
|
|
}
|