Using a IP Camera with IR to detect if it's day or night

I have a Foscam FI9831P V2 in my living room. It switches on it’s IR-leds if it detects that the brightness of the room is too low to get good quality images.

I wanted to use this brightness value to control my accent lights etc. but their API/CGI cannot provide this information.

Correction: Actually the CGI does support it, http:///cgi-bin/CGIProxy.fcgi?usr=user&pwd=pass&cmd=getDevState, as pointed out by @chairstacker below.

So my thought was, can I take a still image and check if it’s in color or grayscale? The answer is Yes! Since I use TinyCam Pro for NVR, I take the still image from there… but it can of course be taken directly from the camera.

bin/dayornight.sh:

#!/bin/bash

TMPFILE=$(mktemp /tmp/dayornight.XXXXXX)
OUTFILE=/home/homeassistant/.homeassistant/whitelist_dir/dayornight.txt

# Fetch still image from Foscam-camera, via TinyCam

curl --basic -u user:pass -o $TMPFILE http://<IP OF TINYCAM:8040/axis-cgi/jpg/image.cgi?cameraId=<CAMERA ID>

if ! file "$TMPFILE" | grep JPEG; then
    echo "File is not an image"
    exit 1
fi

# Get a value. If value is < 0.1, it's a greyscale image. If it's >0.1, it's color
# https://stackoverflow.com/questions/23922654/detect-if-image-is-grayscale-or-color-using-imagick

VALUE_RAW=`convert $TMPFILE -colorspace HSL -channel g -separate +channel -format "%[fx:mean]" info:`

# Multiply by 10 + round off to be able to compare
# <1 = grayscale
# >1 && < 10 = color

VALUE=`echo "$VALUE_RAW * 10" | bc | awk '{print int($1+0.5)}'`

echo $VALUE > $OUTFILE

rm $TMPFILE

Crontab:

# Run dayornight.sh every 5 minutes
*/5 * * * * /home/homeassistant/bin/dayornight.sh >/dev/null 2>&1

configuration.yaml:

homeassistant:
  # To be able to read files from disk
  whitelist_external_dirs:
    - /home/homeassistant/.homeassistant/whitelist_dir

sensor:
  - platform: file
    name: Brightness
    file_path: /home/homeassistant/.homeassistant/whitelist_dir/dayornight.txt

3 Likes

Cool idea!

Does you camera not support CGI?

Mine shows a lot of information, including the infraLedState by using the query:
http://192.168.99.99:88/cgi-bin/CGIProxy.fcgi?cmd=getDevState&usr=admin&pwd=password

<CGI_Result>
    <result>0</result>
    <IOAlarm>0</IOAlarm>
    <motionDetectAlarm>1</motionDetectAlarm>
    <soundAlarm>0</soundAlarm>
    <record>0</record>
    <sdState>0</sdState>
    <sdFreeSpace>0k</sdFreeSpace>
    <sdTotalSpace>0k</sdTotalSpace>
    <ntpState>1</ntpState>
    <ddnsState>0</ddnsState>
    <url>http%3A%2F%2Fgm1234.myfoscam.org%3A88</url>
    <upnpState>0</upnpState>
    <isWifiConnected>0</isWifiConnected>
    <wifiConnectedAP></wifiConnectedAP>
    <infraLedState>0</infraLedState>
</CGI_Result>

You can download the “Foscam IPCamera CGI User Guide-V1.0.4.pdf” from here for example:

Haha… I just can’t believe this :smile: As I wrote in the OP, I was sure that this information was not provided by the CGI. I have read that PDF file before and have experimented with the CGI a bit.

But for some reason… I have missed this. Have I found an older version of the documentation perhaps? I don’t know… but it did work with my camera.

Maybe someone with a camera that doesn’t have this feature can use my work.

Thanks :man_facepalming:

Good that I posted it anyway then :grinning:

Btw, do you fetch any values from this CGI as a sensor in HA? I guess it can be done with the RESTful Sensor but you probably have to figure out how to write a template.

I don’t do anything like that, but yes: I assume it’s either with a RESTful Sensor or a Scrape Sensor.

Could not find any example of handling XML output in the RESTful Sensor.

But, it wasn’t hard getting it to work with curl. Could be done with Python to be able to handle XML but I just used some simple shell commands instead to format the output.

binary_sensor:
  - platform: command_line
    name: Foscam InfraLed
    command: curl -s -X GET "http://<IP OF FOSCAM CAMERA/cgi-bin/CGIProxy.fcgi?usr=admin&pwd=password&cmd=getDevState" | grep infraLedState | sed -e 's/<[^>]*>//g'
    payload_on: 1
    payload_off: 0
    scan_interval: 300

Looks good - guess with a RESTful sensor you might be able to catch the change in realtime rather than having to rely on a scan_interval.