Skip to content

Instantly share code, notes, and snippets.

@sidoh
Created January 16, 2017 23:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sidoh/11ba12d398e6f2d26ea5296caa375905 to your computer and use it in GitHub Desktop.
Save sidoh/11ba12d398e6f2d26ea5296caa375905 to your computer and use it in GitHub Desktop.
import static java.util.UUID.randomUUID
import java.security.MessageDigest
import javax.crypto.spec.SecretKeySpec
import javax.crypto.Mac
import java.security.SignatureException
import groovy.json.JsonOutput
metadata {
// Automatically generated. Make future change here.
definition (name: "HaGateway Camera", namespace: "smartthings", author: "sidoh") {
capability "Actuator"
capability "Image Capture"
capability "Switch"
command "enableRecording"
command "disableRecording"
command "enableRemoteAccess"
command "disableRemoteAccess"
command "enableMotionDetect"
command "disableMotionDetect"
command "gotoPresetOne"
command "gotoPresetTwo"
attribute "remoteAccess", "enum", ["Enabled", "Disabled"]
attribute "motionDetect", "enum", ["Enabled", "Disabled"]
}
preferences {
input "camera", "text", title: "Camera Identifier", displayDuringSetup: true
}
simulator {
// TODO: define status and reply messages here
}
tiles {
standardTile("camera", "device.image", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: true) {
state "default", label: "", action: "", icon: "st.camera.dropcam-centered", backgroundColor: "#FFFFFF"
}
carouselTile("cameraDetails", "device.image", width: 3, height: 2) { }
standardTile("take", "device.image", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
state "take", label: "Take", action: "Image Capture.take", icon: "st.camera.dropcam", backgroundColor: "#FFFFFF", nextState:"taking"
state "taking", label:'Taking', action: "", icon: "st.camera.dropcam", backgroundColor: "#53a7c0"
state "image", label: "Take", action: "Image Capture.take", icon: "st.camera.dropcam", backgroundColor: "#FFFFFF", nextState:"taking"
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.Entertainment.entertainment9", backgroundColor:"#79b821", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.Entertainment.entertainment9", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', icon:"st.Entertainment.entertainment9", backgroundColor:"#79b821"
state "turningOff", label:'${name}', icon:"st.Entertainment.entertainment9", backgroundColor:"#ffffff"
}
standardTile("remoteAccess", "device.remoteAccess", width: 1, height: 1, canChangeIcon: true) {
state "on", label:'Remote Access: ${name}', action:"disableRemoteAccess", icon:"st.Weather.weather15", backgroundColor:"#79b821", nextState:"turningOff"
state "off", label:'Remote Access: ${name}', action:"enableRemoteAccess", icon:"st.Weather.weather15", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'Enabling...', icon:"st.Weather.weather15", backgroundColor:"#79b821"
state "turningOff", label:'Disabling...', icon:"st.Weather.weather15", backgroundColor:"#ffffff"
}
standardTile("motionDetect", "device.motionDetect", width: 1, height: 1, canChangeIcon: true) {
state "on", label:'Motion Detect: ${name}', action:"disableMotionDetect", icon:"st.Wellness.health12", backgroundColor:"#79b821", nextState:"turningOff"
state "off", label:'Motion Detect: ${name}', action:"enableMotionDetect", icon:"st.Wellness.health12", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'Enabling...', icon:"st.Wellness.health12", backgroundColor:"#79b821"
state "turningOff", label:'Disabling...', icon:"st.Wellness.health12", backgroundColor:"#ffffff"
}
standardTile("preset1", "device.preset", width: 1, height: 1, canChangeIcon: true) {
state "1", label: '${name}', backgroundColor:"#79b821", action: "gotoPresetOne"
}
standardTile("preset2", "device.preset", width: 1, height: 1, canChangeIcon: true) {
state "2", label: '${name}', backgroundColor:"#79b821", action: "gotoPresetTwo"
}
main "switch"
details(["cameraDetails", "take", "switch", "remoteAccess", "motionDetect", "preset1", "preset2"])
}
}
def parse(p) {
log.info p
}
def gotoPresetOne() {
gotoPreset(1)
}
def gotoPresetTwo() {
gotoPreset(2)
}
def gotoPreset(preset) {
gwGet("/presets") {
def presets = it.data
def presetName = presets[preset-1]
gwGet("/presets/${presetName}")
}
}
def enableMotionDetect() {
sendEvent(name: "motionDetect", value: "on")
gwPut('', [motionDetection: [enabled: 'true']])
}
def disableMotionDetect() {
sendEvent(name: "motionDetect", value: "off")
gwPut('', [motionDetection: [enabled: 'false']])
}
def enableRemoteAccess() {
sendEvent(name: "remoteAccess", value: "on")
gwPut('', [remoteAccess: true])
}
def disableRemoteAccess() {
sendEvent(name: "remoteAccess", value: "off")
gwPut('', [remoteAccess: false])
}
def on() {
sendEvent(name: "switch", value: "on")
gwPut('', [recording: true])
}
def off() {
sendEvent(name: "switch", value: "off")
gwPut('', [recording: false])
}
def take() {
log.info "Executing 'take'"
gwGet('/snapshot.jpg') {
final def imageName = "${randomUUID() as String}.jpg"
storeImage(imageName, it.data)
}
}
def hmac(String data, String key) throws SignatureException {
final Mac hmacSha1;
try {
hmacSha1 = Mac.getInstance("HmacSHA1");
} catch (Exception nsae) {
hmacSha1 = Mac.getInstance("HMAC-SHA-1");
}
final SecretKeySpec macKey = new SecretKeySpec(key.getBytes(), "RAW");
hmacSha1.init(macKey);
final byte[] signature = hmacSha1.doFinal(data.getBytes());
return signature.encodeHex()
}
def getHmacHeaders(path, params = [:], body = "") {
long time = new Date().getTime()
time /= 1000L
final def payload = path + params.sort { it.key }.inject('') { a,k,v -> a+k+v } + body + time
final String signature = hmac(payload, '<your hmac secret here>')
[
'X-Signature-Timestamp': time,
'X-Signature-Payload': payload,
'X-Signature': signature
]
}
def setPreset(preset) {
gwPut('', [preset: preset])
runIn(2, take)
sendEvent(name: 'preset', value: preset)
}
def gwPost(path, params, success = {}) {
def requestPath = "/cameras/${settings.camera}${path}"
def body = JsonOutput.toJson(params)
httpPost(
[
uri: "http://hagw.sidoh.org${requestPath}",
requestContentType: 'application/json',
body: body,
headers: getHmacHeaders(requestPath, [], body),
success: success
]
)
}
def gwPut(path, params, success = {}) {
def requestPath = "/cameras/${settings.camera}${path}"
def body = JsonOutput.toJson(params)
httpPut(
[
uri: "http://<hagw url here>${requestPath}",
requestContentType: 'application/json',
body: body,
headers: getHmacHeaders(requestPath, [], body),
success: success
]
)
}
def gwGet(path, success = {}) {
def requestPath = "/cameras/${settings.camera}${path}"
httpGet(
[
uri: "http://hagw.sidoh.org${requestPath}",
headers: getHmacHeaders(requestPath),
success: success
]
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment