Android IP Camera Device

Yes, the values are set at the device. Sound should be possible, but not implemented yet.

preferences
{
	input("username",	"text",		title: "Camera username",	description: "Username for web login")
	input("password",	"password",	title: "Camera password",	description: "Password for web login")
	input("url",		"text",		title: "IP or URL of camera",	description: "Do not include http://")
	input("port",		"text",		title: "Port",			description: "Port")
}

metadata {
	definition (name: "Android IP Camera Beta", author: "Alan", namespace: "alt") {
		capability "Image Capture"
		capability "Switch"
		capability "Actuator"
		capability "Battery"
       	capability "Illuminance Measurement"
		capability "Temperature Measurement"
        capability "Motion Sensor"

		command "ledOn"
		command "ledOff"
		command "focusOn"
		command "focusOff"
		command "overlayOn"
		command "overlayOff"
		command "nightVisionOn"
		command "nightVisionOff"
		command "refresh"


	}

	tiles {
		carouselTile("cameraDetails", "device.image", width: 3, height: 2) { }

		standardTile("camera", "device.image", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: true) {
			state("default", label: '', action: "Image Capture.take", icon: "st.camera.camera", backgroundColor: "#FFFFFF")
		}

		standardTile("take", "device.image", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false, decoration: "flat") {
			state("take", label: 'Take Photo', action: "Image Capture.take", icon: "st.camera.take-photo", nextState:"taking")
			state("taking", label: 'Taking...', action: "Image Capture.take", icon: "st.camera.take-photo", backgroundColor: "#79b821")
		}

		standardTile("record", "device.switch", width: 1, height: 1) {
			state("recordOff", label: 'Record Off', action:"switch.on", icon:"st.switches.light.off", backgroundColor: "#ffffff")
			state("recordOn", label: 'Record On', action:"switch.off", icon:"st.switches.light.on", backgroundColor: "#79b821")
		}




		standardTile("led", "device.led", width: 1, height: 1) {
			state("ledOff", label: 'Led Off', action:"ledOn", icon:"st.switches.light.off", backgroundColor: "#ffffff")
			state("ledOn", label: 'Led On', action:"ledOff", icon:"st.switches.light.on", backgroundColor: "#79b821")
		}

		standardTile("focus", "device.focus", width: 1, height: 1) {
			state("focusOff", label: 'Focus Off', action:"focusOn", icon:"st.switches.light.off", backgroundColor: "#ffffff")
			state("focusOn", label: 'Focus On', action:"focusOff", icon:"st.switches.light.on", backgroundColor: "#79b821")
		}

		standardTile("overlay", "device.overlay", width: 1, height: 1) {
			state("overlayOff", label: 'Overlay Off', action:"overlayOn", icon:"st.switches.light.off", backgroundColor: "#ffffff")
			state("overlayOn", label: 'Overlay On', action:"overlayOff", icon:"st.switches.light.on", backgroundColor: "#79b821")
		}

		standardTile("nightVision", "device.nightVision", width: 1, height: 1) {
			state("nightVisionOff", label: 'Night Vision Off', action:"nightVisionOn", icon:"st.switches.light.off", backgroundColor: "#ffffff")
			state("nightVisionOn", label: 'Night Vision On', action:"nightVisionOff", icon:"st.switches.light.on", backgroundColor: "#79b821")
		}


		valueTile("battery", "device.battery", decoration: "flat", width: 1, height: 1) {
			state "battery", label:'${currentValue}% battery', unit:""
		}
        
		valueTile("light", "device.illuminance", inactiveLabel: false, width: 1, height: 1, decoration: "flat", wordWrap: true) {
			state "default", label:'Lux\n${currentValue}'
		}

		valueTile("magnetic", "device.magnetic", inactiveLabel: false, width: 1, height: 1, decoration: "flat", wordWrap: true) {
			state "default", label:'Mag\n${currentValue}'
		}
		valueTile("magy", "device.magy", inactiveLabel: false, width: 1, height: 1, decoration: "flat", wordWrap: true) {
			state "default", label:'Magy\n${currentValue}'
		}
		valueTile("magz", "device.magz", inactiveLabel: false, width: 1, height: 1, decoration: "flat", wordWrap: true) {
			state "default", label:'Magz\n${currentValue}'
		}
		multiAttributeTile(name: "motion", type: "generic", width: 3, height: 2) {
			tileAttribute("device.motionevent", key: "PRIMARY_CONTROL") {
				attributeState "1.0", label: 'motion', icon: "st.motion.motion.active", backgroundColor: "#53a7c0"
				attributeState "0", label: 'no motion', icon: "st.motion.motion.inactive", backgroundColor: "#ffffff"
			}
            }
		main "camera"
		details(["cameraDetails","camera","take","record","led","focus","overlay","nightVision","battery","light","motion","magnetic","magy","magz"])
	}
}


def parseCameraResponse(def response) {
	if(response.headers.'Content-Type'.contains("image/jpeg")) {
		def imageBytes = response.data

		if(imageBytes) {
			storeImage(getPictureName(), imageBytes)
		}
	} else {
		log.error("${device.label} could not capture an image.")
	}
}

private getPictureName() {
	def pictureUuid = java.util.UUID.randomUUID().toString().replaceAll('-', '')
	"image" + "_$pictureUuid" + ".jpg"
}

private take() {
	log.info("${device.label} taking photo")

	httpGet("http://${username}:${password}@${url}:${port}/photo_save_only.jpg"){
		httpGet("http://${username}:${password}@${url}:${port}/photo.jpg"){
			response -> log.info("${device.label} image captured")
			parseCameraResponse(response)
		}
	}
}

def on(theSwitch="record") {
	def sUrl
	switch ( theSwitch ) {
		case "led":
			sUrl = "enabletorch"
			break

		case "focus":
			sUrl = "focus"
			break

		case "overlay":
			sUrl = "settings/overlay?set=on"
			break

		case "nightVision":
			sUrl = "settings/night_vision?set=on"
			break

		default:
			sUrl = "/startvideo?force=1"
	}

	httpGet("http://${username}:${password}@${url}:${port}/${sUrl}"){
		response -> log.info("${device.label} ${theSwitch} On")
		sendEvent(name: "${theSwitch}", value: "${theSwitch}On")
	}

}

def off(theSwitch="record") {
	def sUrl
	switch ( theSwitch ) {
		case "led":
			sUrl = "disabletorch"
			break

		case "focus":
			sUrl = "nofocus"
			break

		case "overlay":
			sUrl = "settings/overlay?set=off"
			break

		case "nightVision":
			sUrl = "settings/night_vision?set=off"
			break

		default:
			sUrl = "stopvideo?force=1"
	}

	httpGet("http://${username}:${password}@${url}:${port}/${sUrl}"){
		response -> log.info("${device.label} ${theSwitch} Off")
		sendEvent(name: "${theSwitch}", value: "${theSwitch}Off")
	}

}

def ledOn() { on("led") }

def ledOff() { off("led") }

def focusOn() { on("focus") }

def focusOff() { off("focus") }

def overlayOn() { on("overlay") }

def overlayOff() { off("overlay") }

def nightVisionOn() { on("nightVision") }

def nightVisionOff() { off("nightVision") }

def installed() { runPeriodically(20*60, poll) }

def configure() { poll() }

def poll() { refresh() }

def refresh() { getSensors() }

def cToF(temp) {
	return temp * 1.8 + 32
}

def getSensors() {

	def params = [
		uri: "http://${username}:${password}@${url}:${port}",
		path: "/sensors.json",
		contentType: 'application/json'
	]

	log.debug "Params = ${params}"

	def theSensor
	def theUnit
	def theData
    def n

	try {
		httpGet(params) { 
			response -> log.debug "Start httpGet"
			response.data.each {
				key,value -> theSensor = key
				theUnit = value.unit
				if (value.data[0][1].size() == 1) {
					theData = value.data[0][1].first() 
					if (theSensor == "battery_level") {theSensor = "battery"}
					if (theSensor == "battery_temp") {
						theSensor = "device temperature"
						theUnit = "F"
						theData = cToF(theData as Integer)
                    }
					if (theSensor == "ambient_temp") {
						theSensor = "temperature"
						theUnit = "F"
						theData = cToF(theData as Integer)
                    }

                    if (theSensor == "battery_voltage") {
                    	theSensor = "battery Volt"
                    }
                    

					if (theSensor == "light") {
						theSensor = "illuminance"
						theUnit = "lux"
					}
                    
                    if (theSensor == "motion_event") {
                    	theSensor = "motionevent"
                        		
                    }
		
					log.info "name: ${theSensor}, value: ${theData}, unit: ${theUnit}"
					sendEvent(name:"${theSensor}", value: theData as Integer, unit:"${theUnit}")
    
               } else { theData = value.data[0][1] }
				log.debug "${theSensor}: ${theUnit} ${theData}"
			}
		}
	}
	catch(e) { log.debug "$e" }
}
2 Likes