Foscam Universal Internal Device Type (HD\Non-HD with Alarm\LED\PTZ Control)

@eparkerjr Rboy appears to have added live video streaming. Do you intend to do the same?

Hi, I have this device type working with my foscam FI9800P, one question, I would like to setup an automation where when the camera detects motion it takes pictures. I can do this on the foscam itself, but would prefer it is in the smartthings app. Is there a way to do this without buying Rboys stuff?

Do you guys happen to know if there is a motion sensor device type that can be used in conjunction with this. I’m using the https://www.npmjs.com/package/homebridge-foscamcamera plugin with apple home kit now and it works well. It comes with the ability to receive snaps every 10 seconds and set the motion sensor with different modes.

I go foscam connect to work now.

I need the full code for ptz and smartthings

I’m using code https://github.com/lacbra/st_foscam_hd

No signature of method: script1484770592804289503705.metadata() is applicable for argument types: (script1484770592804289503705$_run_closure2) values: [script1484770592804289503705$_run_closure2@24b92b18] Possible solutions: getMetadata(), getState(), setState(java.lang.Object), metaClass(groovy.lang.Closure)

Using a Foscam C1 and having no luck. I tried lowering the streaming quality, nothing… I can see a stream of it from my phone using an android app (ip camera viewer) , but nothing in the ST app. I even tried the ‘Take’ Button. I do see something in my log:

I do not see anything in my camera’s log. Do I need to enable something on the camera? My camera’s firmware is 2.52.2.5
When I manually try to view an image (/cgi-bin/CGIProxy.fcgi?usr=admin&pwd=xxx&cmd=snapPicture2), I get a picture returned in the browser.
Here is my ST app settings for the device:

i dont see my foscam camera as camera in home when i am using homebridge… did you do something different

It looks like the map variables have changed. I fixed the camera not taking pictures by looking at the API documentation. http://docs.smartthings.com/en/latest/cloud-and-lan-connected-device-types-developers-guide/working-with-images.html

It looks like there is no longer a “bucket” and “key”, but now they use “tempImageKey”.

Changed the parse() function

    def descMap = parseDescriptionAsMap(description)
    
//Image
if (map.tempImageKey) {
    try {
        storeTemporaryImage(map.tempImageKey, getPictureName())
    } catch (Exception e) {
        log.error e
    }
} else if (map.error) {
    log.error "Error: ${map.error}"
}
//if (descMap["bucket"] && descMap["key"]) {
//	putImageInS3(descMap)
//}

I am using a 8910W.

what code are you using… didnt see a function storeTemporaryImage

never mind… i see its a ST function
this is the last line i see after i take the picture but still no result in the carouselTile

debug Parsing ‘index:18, mac:E8ABFA585BDF, ip:C0A8010B, port:0058, requestId:e75d54ae-289c-482c-9146-f99c1c312169, tempImageKey:742ac53c-5b81-4b8c-b1d6-cf4f5249e13e’

yea… i had that issue for a while…

storeTemporaryImage was depricated.
replace 'storeTemporaryImage with putImageInS3

here is my parse:

def parse(String description) {
log.debug "Parsing '${description}'"

def map = [:]
def retResult = []
def descMap = parseDescriptionAsMap(description)
    
//Image
if (descMap["bucket"] && descMap["key"]) {
	putImageInS3(descMap)
}

//Status Polling
else if (descMap["headers"] && descMap["body"]) {
    def body = new String(descMap["body"].decodeBase64())
    if(hdcamera == true) {
        def langs = new XmlSlurper().parseText(body)

        def motionAlarm = "$langs.isEnable"
        def ledMode = "$langs.mode"

        //Get Motion Alarm Status
        if(motionAlarm == "0") {
            log.info("Polled: Alarm Off")
            sendEvent(name: "alarmStatus", value: "off");
        }
        else if(motionAlarm == "1") {
            log.info("Polled: Alarm On")
            sendEvent(name: "alarmStatus", value: "on");
        }

        //Get IR LED Mode
        if(ledMode == "0") {
            log.info("Polled: LED Mode Auto")
            sendEvent(name: "ledStatus", value: "auto")
        }
        else if(ledMode == "1") {
            log.info("Polled: LED Mode Manual")
            sendEvent(name: "ledStatus", value: "manual")
        }
	}
    else {
    	if(body.find("alarm_motion_armed=0")) {
			log.info("Polled: Alarm Off")
            sendEvent(name: "alarmStatus", value: "off")
        }
    	else if(body.find("alarm_motion_armed=1")) {
			log.info("Polled: Alarm On")
            sendEvent(name: "alarmStatus", value: "on")
        }
        //The API does not provide a way to poll for LED status on 8xxx series at the moment
    }
}
}
def parseDescriptionAsMap(description) {
	description.split(",").inject([:]) { map, param ->
		def nameAndValue = param.split(":")
		map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
	}
}

peter, i think the putImageInS3 is the one deprecated and not the storeTemporaryImage
putImageInS3 was something which is using getS3Object which is deprecated

def putImageInS3(map) {

def s3ObjectContent

try {
	def imageBytes = getS3Object(map.bucket, map.key + ".jpg")

	if(imageBytes)
	{
		s3ObjectContent = imageBytes.getObjectContent()
		def bytes = new ByteArrayInputStream(s3ObjectContent.bytes)
		storeImage(getPictureName(), bytes)
	}
}
catch(Exception e) {
	log.error e
}
finally {
	//Explicitly close the stream
	if (s3ObjectContent) { s3ObjectContent.close() }
}

}

i made some progress now something shows up on the app its just all black so have to see what image its picking up … earlier it was all white… so i guess i made some progress… :slight_smile:

I must of given you an old DH version or something… sorry… glad it’s working

This is what I see now. The SmartThings logo on the app when I click on it then it takes me too the picture which is all black

Sorry, I was using the code in the original post on GitHub. Here is my parse() updated:

//Parse events into attributes
def parse(String description) {
log.debug "Parsing '${description}'"

def map = [:]
def retResult = []
def descMap = parseDescriptionAsMap(description)
    
//Image
if (descMap.tempImageKey) {
    try {
        storeTemporaryImage(descMap.tempImageKey, getPictureName())
    } catch (Exception e) {
        log.error e
    }
} else if (descMap.error) {
    log.error "Error: ${descMap.error}"
}

//Status Polling
else if (descMap["headers"] && descMap["body"]) {
    def body = new String(descMap["body"].decodeBase64())
    if(hdcamera == true) {
        def langs = new XmlSlurper().parseText(body)

        def motionAlarm = "$langs.isEnable"
        def ledMode = "$langs.mode"

        //Get Motion Alarm Status
        if(motionAlarm == "0") {
            log.info("Polled: Alarm Off")
            sendEvent(name: "alarmStatus", value: "off");
        }
        else if(motionAlarm == "1") {
            log.info("Polled: Alarm On")
            sendEvent(name: "alarmStatus", value: "on");
        }

        //Get IR LED Mode
        if(ledMode == "0") {
            log.info("Polled: LED Mode Auto")
            sendEvent(name: "ledStatus", value: "auto")
        }
        else if(ledMode == "1") {
            log.info("Polled: LED Mode Manual")
            sendEvent(name: "ledStatus", value: "manual")
        }
	}
    else {
    	if(body.find("alarm_motion_armed=0")) {
			log.info("Polled: Alarm Off")
            sendEvent(name: "alarmStatus", value: "off")
        }
    	else if(body.find("alarm_motion_armed=1")) {
			log.info("Polled: Alarm On")
            sendEvent(name: "alarmStatus", value: "on")
        }
        //The API does not provide a way to poll for LED status on 8xxx series at the moment
    }
}
}

my parse is exaacly the same but still dont see the image in the app, just a black picture

5880f8fc-5e54-41c6-863a-21fb2d4faa52 2:42:45 PM: debug Storing image
5880f8fc-5e54-41c6-863a-21fb2d4faa52 2:42:45 PM: debug Parsing desc ‘index:18, mac:E8ABFA585BDF, ip:C0A8010B, port:0058, requestId:4b841dd4-e1c5-46df-8d5c-ab51cd6bc56a, tempImageKey:b72757d4-3972-492b-98c8-a1adb7857bf1’
5880f8fc-5e54-41c6-863a-21fb2d4faa52 2:42:43 PM: debug Device Network Id set to c0a8010b:0058

def parse(String description) {
log.debug “Parsing desc ‘${description}’”
def map = [:]
def retResult =
def descMap = parseDescriptionAsMap(description)
// def map = stringToMap(description)

//Image
if (descMap.tempImageKey) {
try {
	log.debug "Storing image  "
    storeTemporaryImage(descMap.tempImageKey, getPictureName())
   
} catch (Exception e) {
    log.error e
}
	} else if (descMap.error) {
		log.error "Error: ${map.error}"
}

//Status Polling
else if (descMap["headers"] && descMap["body"]) {
    def body = new String(descMap["body"].decodeBase64())
    if(hdcamera == true) {
        def langs = new XmlSlurper().parseText(body)

        def motionAlarm = "$langs.isEnable"
        def ledMode = "$langs.mode"

        //Get Motion Alarm Status
        if(motionAlarm == "0") {
            log.info("Polled: Alarm Off")
            sendEvent(name: "alarmStatus", value: "off");
        }
        else if(motionAlarm == "1") {
            log.info("Polled: Alarm On")
            sendEvent(name: "alarmStatus", value: "on");
        }

        //Get IR LED Mode
        if(ledMode == "0") {
            log.info("Polled: LED Mode Auto")
            sendEvent(name: "ledStatus", value: "auto")
        }
        else if(ledMode == "1") {
            log.info("Polled: LED Mode Manual")
            sendEvent(name: "ledStatus", value: "manual")
        }
	}
    else {
    	if(body.find("alarm_motion_armed=0")) {
			log.info("Polled: Alarm Off")
            sendEvent(name: "alarmStatus", value: "off")
        }
    	else if(body.find("alarm_motion_armed=1")) {
			log.info("Polled: Alarm On")
            sendEvent(name: "alarmStatus", value: "on")
        }
        //The API does not provide a way to poll for LED status on 8xxx series at the moment
    }
}

}
def parseDescriptionAsMap(description) {
description.split(“,”).inject([:]) { map, param →
def nameAndValue = param.split(“:”)
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
}

@psun03 Peter can you share your take and hubget too… it seems like when the endpoint is correct then the hubget hangs but when endpoint is incorrrect it is inserting XML text on smartthings

orrect endpoint
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:43:31 PM: debug HD is true snapPicture2
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:43:31 PM: debug device current Value s3
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:43:31 PM: debug HD uri is /cgi-bin/CGIProxy.fcgi?usr=user &pwd=pwd&cmd=snapPicture2
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:43:31 PM: debug Executing hubaction on 192.168.1.11:88
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:43:31 PM: debug Device Network Id set to c0a8010b:0058
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:43:31 PM: debug Taking Photo

incorrect endoint
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:50 PM: debug store Image
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:50 PM: debug Parsing 'index:18, mac:E8ABFA585BDF, ip:C0A8010B, port:0058, requestId:e0f53aa7-0b25-439b-94bf-fdcb4030e857, tempImageKey:1d0c9305-338b-4312-b6cb-c5d2a19915b1’
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:49 PM: debug device current Value s3
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:49 PM: debug HD uri is /cgi-bin/CGIProxy.fcgi?usr=user&pwd=pwd&/snapshot.cgi? – incorrect endpoint
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:49 PM: debug Executing hubaction on 192.168.1.11:88
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:49 PM: debug Device Network Id set to c0a8010b:0058
5880f8fc-5e54-41c6-863a-21fb2d4faa52 5:42:49 PM: debug Taking Photo

<CGI_Result>
-3
</CGI_Result>

Here is my getHub and some other functions that may help:

private getLogin() {
	if(hdcamera == true) {
    	return "usr=${username}&pwd=${password}&"
    }
    else {
    	return "user=${username}&pwd=${password}"
    }
}

private hubGet(def apiCommand) {
	//Setting Network Device Id
    def iphex = convertIPtoHex(ip)
    def porthex = convertPortToHex(port)
    device.deviceNetworkId = "$iphex:$porthex"
    log.debug "Device Network Id set to ${iphex}:${porthex}"

	log.debug("Executing hubaction on " + getHostAddress())
    def uri = ""
    if(hdcamera == true) {
    	uri = "/cgi-bin/CGIProxy.fcgi?" + getLogin() + apiCommand
	}
    else {
    	uri = apiCommand + getLogin()
    }
    log.debug uri
    def hubAction = new physicalgraph.device.HubAction(
    	method: "GET",
        path: uri,
        headers: [HOST:getHostAddress()]
    )
    if(device.currentValue("hubactionMode") == "s3") {
        hubAction.options = [outputMsgToS3:true]
        sendEvent(name: "hubactionMode", value: "local");
    }
	hubAction
}

didnt work… for some reason the parse method isnt called if the endpoint is correct…

do you have a link to your code or something i can see

here it is

https://pastebin.com/Ed8rPQFW

So, your code looks correct, but one thing i would change which probably won’t in pack your issue… I would change this function

def parseDescriptionAsMap(description) {
	log.debug "Function: parseDescriptionAsMap"
    return description.split(',')*.trim()*.tokenize(':').collectEntries()
 }

So I don’t know why it isn’t working. These are the steps I would take to isolate the issue. Is it the camera or smartthings hub/app or the code.

  1. Is the camera taking a snapshot.
    I would manually send the command to the camera in the web browser and see if you get a snapshot back in the web browser. (I assume you have a C1). If you see black, then the camera is your issue. I would look for an firmware update or call foscam.

  2. What version of the app are you using? I heard there were issues with the Android app for a while. It should be fixed. I am using the Android app and it works just fine.

  3. Can you turn on and off the led from the ST app?

  4. What version of the ST hub are you using?

I don’t see anything wrong with your code except for the function i mentioned above.