Terrarium Controller


Using pilight to keep your lizards happy

One of our faithfull users Terrar has fully automated his terrarium control by using pilight. This is how he set it up.

Requirements

  • switch the lamps automatically on the correct time
  • keep temperature and humidity stable (day and night settings are different) with:
  1. humidifier
  2. fans
  3. dimming spots
  • simulate sunrise and sunset with the dimmers (not done yet)

Hardware

  • Raspberry Pi B
  • 1x RTC DS1307
  • 4x DS18B20
  • 1x DHT11
  • 1x 4 channel relay for humidifier, T5 neonlamps, fans
  • 2x COCO Dimmer

After wiring all this hardware there is no GPIO left on the raspberry.

{
    "devices": {
        "zeit": {
            "protocol": [ "datetime" ],
            "id": [{
                "longitude": "xx.xxxx",
                "latitude": "xx.xxxx",
                "ntpserver": "xxxx.org"
            }],
            "year": 2014,
            "month": 12,
            "day": 26,
            "hour": 2,
            "minute": 36,
            "second": 45
        },
        "humi": {
            "protocol": [ "dht11" ],
            "id": [{
                "gpio": 6
            }],
            "humidity": 36.0,
            "temperature": 22.0,
            "poll-interval": 10
        },
        "templio": {
            "protocol": [ "d6s18b20" ],
            "id": [{
                "id": "000461235eff"
            }],
            "temperature": 21.937,
            "poll-interval": 10
        },
        "templiu": {
            "protocol": [ "ds18b20" ],
            "id": [{
                "id": "000461239cff"
            }],
            "temperature": 22.125,
            "poll-interval": 10
        },
        "tempreo": {
            "protocol": [ "ds18b20" ],
            "id": [{
                "id": "000461239cff"
            }],
            "temperature": 22.125,
            "poll-interval": 10
        },
        "tempreu": {
            "protocol": [ "ds18b20" ],
            "id": [{
                "id": "0004641794ff"
            }],
            "temperature": 22.000,
            "poll-interval": 10
        },
        "neon": {
            "protocol": [ "relay" ],
            "id": [{
                "gpio": 2
            }],
            "state": "on"
        },
        "fog": {
            "protocol": [ "relay" ],
            "id": [{
                "gpio": 3
            }],
            "state": "off"
        },
        "airfog": {
            "protocol": [ "relay" ],
            "id": [{
                "gpio": 4
            }],
            "state": "off"
        },
        "airair": {
            "protocol": [ "relay" ],
            "id": [{
                "gpio": 5
            }],
            "state": "off"
        },
        "spotli": {
            "protocol": [ "kaku_dimmer" ],
            "id": [{
                "id": 1111,
                "unit": 0
            }],
            "state": "on",
            "dimlevel-minimum": 0,
            "dimlevel-maximum": 15,
            "dimlevel": 15
        },
        "spotre": {
            "protocol": [ "kaku_dimmer" ],
            "id": [{
                "id": 2222,
                "unit": 0
            }],
            "state": "on",
            "dimlevel-minimum": 0,
            "dimlevel-maximum": 15,
            "dimlevel": 15
        },
        "vtempd": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 20
            }],
            "state": "on",
            "dimlevel-minimum": 10,
            "dimlevel-maximum": 90,
            "dimlevel": 22
        },
        "vtempn": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 21
            }],
            "state": "on",
            "dimlevel-minimum": 10,
            "dimlevel-maximum": 90,
            "dimlevel": 22
        },
        "vtempsli": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 22
            }],
            "state": "on",
            "dimlevel-minimum": 35,
            "dimlevel-maximum": 55,
            "dimlevel": 45
        },
        "vtempsre": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 23
            }],
            "state": "on",
            "dimlevel-minimum": 35,
            "dimlevel-maximum": 55,
            "dimlevel": 45
        },
        "vhumid": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 24
            }],
            "state": "on",
            "dimlevel-minimum": 10,
            "dimlevel-maximum": 90,
            "dimlevel": 36
        },
        "vhumin": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 25
            }],
            "state": "on",
            "dimlevel-minimum": 10,
            "dimlevel-maximum": 90,
            "dimlevel": 36
        },
        "vtimed": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 26
            }],
            "state": "on",
            "dimlevel-minimum": 1,
            "dimlevel-maximum": 12,
            "dimlevel": 1
        },
        "vtimen": {
            "protocol": [ "generic_dimmer" ],
            "id": [{
                "id": 27
            }],
            "state": "on",
            "dimlevel-minimum": 12,
            "dimlevel-maximum": 23,
            "dimlevel": 18
        },
        "rlamps": {
            "protocol": [ "generic_switch" ],
            "id": [{
                "id": 30
            }],
            "state": "on"
        },
        "rfog": {
            "protocol": [ "generic_switch" ],
            "id": [{
                "id": 31
            }],
            "state": "on"
        },
        "rfans": {
            "protocol": [ "generic_switch" ],
            "id": [{
                "id": 32
            }],
            "state": "on"
        }
    },
    "rules": {
        "unfinished_spotli_sunrise_waiting_for_MINUS_and_PLUS_feature": {
            "rule": "IF spotli.dimlevel != spotli.dimlevel-maximum AND zeit.hour >= vtimed.dimlevel AND zeit.hour < (vtimed.dimlevel + 1) AND zeit.second == 00 AND (zeit.minute == 01 OR zeit.minute == 02 OR zeit.minute == 03 OR zeit.minute == 04 OR zeit.minute == 05 OR zeit.minute == 06 OR zeit.minute == 07 OR zeit.minute == 08 OR zeit.minute == 09 OR zeit.minute == 10 OR zeit.minute == 11 OR zeit.minute == 12 OR zeit.minute == 13 OR zeit.minute == 14 OR zeit.minute == 15) THEN dim DEVICE spotli TO 15",
            "active": 1
        },
        "unfinished_spotre_sunrise_waiting_for_MINUS_and_PLUS_feature": {
            "rule": "IF spotre.dimlevel != spotre.dimlevel-maximum AND zeit.hour >= vtimed.dimlevel AND zeit.hour < (vtimed.dimlevel + 1) AND zeit.second == 00 AND (zeit.minute == 01 OR zeit.minute == 02 OR zeit.minute == 03 OR zeit.minute == 04 OR zeit.minute == 05 OR zeit.minute == 06 OR zeit.minute == 07 OR zeit.minute == 08 OR zeit.minute == 09 OR zeit.minute == 10 OR zeit.minute == 11 OR zeit.minute == 12 OR zeit.minute == 13 OR zeit.minute == 14 OR zeit.minute == 15) THEN dim DEVICE spotre TO 15",
            "active": 1
        },
        "unfinished_spotli_sunset_waiting_for_MINUS_and_PLUS_feature": {
            "rule": "IF spotli.dimlevel != spotli.dimlevel-minimum AND zeit.hour >= vtimen.dimlevel AND zeit.hour < (vtimen.dimlevel + 1) AND zeit.second == 00 AND (zeit.minute == 01 OR zeit.minute == 02 OR zeit.minute == 03 OR zeit.minute == 04 OR zeit.minute == 05 OR zeit.minute == 06 OR zeit.minute == 07 OR zeit.minute == 08 OR zeit.minute == 09 OR zeit.minute == 10 OR zeit.minute == 11 OR zeit.minute == 12 OR zeit.minute == 13 OR zeit.minute == 14 OR zeit.minute == 15) THEN dim DEVICE spotli TO 0",
            "active": 1
        },
        "unfinished_spotre_sunset_waiting_for_MINUS_and_PLUS_feature": {
            "rule": "IF spotre.dimlevel != spotre.dimlevel-minimum AND zeit.hour >= vtimen.dimlevel AND zeit.hour < (vtimen.dimlevel + 1) AND zeit.second == 00 AND (zeit.minute == 01 OR zeit.minute == 02 OR zeit.minute == 03 OR zeit.minute == 04 OR zeit.minute == 05 OR zeit.minute == 06 OR zeit.minute == 07 OR zeit.minute == 08 OR zeit.minute == 09 OR zeit.minute == 10 OR zeit.minute == 11 OR zeit.minute == 12 OR zeit.minute == 13 OR zeit.minute == 14 OR zeit.minute == 15) THEN dim DEVICE spotre TO 0",
            "active": 1
        },
        "spotli_off_when_dimlevel_0": {
            "rule": "IF spotli.dimlevel == spotli.dimlevel-minimum AND spotli.state IS on THEN switch DEVICE spotli TO off",
            "active": 1
        },
        "spotre_off_when_dimlevel_0": {
            "rule": "IF spotre.dimlevel == spotre.dimlevel-minimum AND spotre.state IS on THEN switch DEVICE spotre TO off",
            "active": 1
        },
        "spotli_to_dimlevel_0_when_night": {
            "rule": "IF rlamps.state IS on AND spotli.dimlevel != spotli.dimlevel-minimum AND (zeit.hour < vtimed.dimlevel OR zeit.hour > (vtimen.dimlevel + 1)) THEN dim DEVICE spotli TO 0",
            "active": 1
        },
        "spotre_to_dimlevel_0_when_night": {
            "rule": "IF rlamps.state IS on AND spotre.dimlevel != spotre.dimlevel-minimum AND (zeit.hour < vtimed.dimlevel OR zeit.hour > (vtimen.dimlevel + 1)) THEN dim DEVICE spotre TO 0",
            "active": 1
        },
        "spotli_on_runcheck": {
            "rule": "IF rlamps.state IS on AND spotli.dimlevel != spotli.dimlevel-minimum AND spotli.state IS off AND zeit.hour > vtimed.dimlevel AND zeit.hour < vtimen.dimlevel THEN switch DEVICE spotli TO on",
            "active": 1
        },
        "spotre_on_runcheck": {
            "rule": "IF rlamps.state IS on AND spotre.dimlevel != spotre.dimlevel-minimum AND spotre.state IS off AND zeit.hour > vtimed.dimlevel AND zeit.hour < vtimen.dimlevel THEN switch DEVICE spotre TO on",
            "active": 1
        },
        "neon_on_after_sunrise": {
            "rule": "IF zeit.hour >= vtimed.dimlevel AND zeit.hour < (vtimed.dimlevel + 1) AND neon.state IS off AND spotli.dimlevel == spotli.dimlevel-maximum AND spotre.dimlevel == spotre.dimlevel-maximum THEN switch DEVICE neon TO on",
            "active": 1
        },
        "neonlicht_off_before_sunset": {
            "rule": "IF zeit.hour == vtimen.dimlevel AND zeit.minute == 00 AND zeit.second == 30 AND neon.state IS on THEN switch DEVICE neon TO off",
            "active": 1
        },
        "neonlicht_day_on": {
            "rule": "IF rlamps.state IS on AND zeit.hour > vtimed.dimlevel AND zeit.hour < (vtimen.dimlevel - 1) AND neon.state IS off THEN switch DEVICE neon TO on",
            "active": 1
        },
        "neonlicht_night_off": {
            "rule": "IF (zeit.hour > vtimen.dimlevel AND zeit.hour <= 24) OR (zeit.hour >= 0 AND zeit.hour < vtimed.dimlevel) AND rlamps.state IS on AND neon.state IS on THEN switch DEVICE neon TO off",
            "active": 1
        },
        "airfog_on": {
            "rule": "IF rfans.state IS on AND fog.state IS on AND (zeit.second == 00 OR zeit.second == 10 OR zeit.second == 20 OR zeit.second == 30 OR zeit.second == 40 OR zeit.second == 50) THEN switch DEVICE airfog TO on",
            "active": 1
        },
        "airfog_off": {
            "rule": "IF rfans.state IS on AND airfog.state IS on AND (zeit.second == 03 OR zeit.second == 13 OR zeit.second == 23 OR zeit.second == 33 OR zeit.second == 43 OR zeit.second == 53) THEN switch DEVICE airfog TO off",
            "active": 1
        },
        "humi_day_to_high_switch_airair_on": {
            "rule": "IF rfans.state IS on AND humi.humidity != 0 AND humi.humidity > (vhumid.dimlevel + 5) AND zeit.hour >= vtimed.dimlevel AND zeit.hour < vtimen.dimlevel AND airair.state IS off THEN switch DEVICE airair TO on",
            "active": 1
        },
        "humi_day_ok_switch_airair_off": {
            "rule": "IF rfans.state IS on AND humi.humidity != 0 AND humi.humidity >= (vhumid.dimlevel - 5) AND humi.humidity <= (vhumid.dimlevel + 5) AND zeit.hour >= vtimed.dimlevel AND zeit.hour < vtimen.dimlevel AND airair.state IS on THEN switch DEVICE airair TO off",
            "active": 1
        },
        "humi_day_to_low_switch_fog_on": {
            "rule": "IF rfog.state IS on AND (zeit.hour >= vtimed.dimlevel AND zeit.hour < vtimen.dimlevel) AND humi.humidity != 0 AND humi.humidity < (vhumid.dimlevel - 5) THEN switch DEVICE fog TO on",
            "active": 1
        },
        "humi_day_ok_switch_fog_off": {
            "rule": "IF rfog.state IS on AND (zeit.hour >= vtimed.dimlevel AND zeit.hour < vtimen.dimlevel) AND humi.humidity != 0 AND humi.humidity >= (vhumid.dimlevel - 5) AND humi.humidity <= (vhumid.dimlevel + 5) THEN switch DEVICE fog TO off",
            "active": 1
        },
        "humi_night_to_low_switch_fog_on": {
            "rule": "IF rfog.state IS on AND ((zeit.hour >= vtimen.dimlevel AND zeit.hour < 24) OR (zeit.hour >= 0 AND zeit.hour < vtimed.dimlevel)) AND humi.humidity != 0 AND humi.humidity < (vhumin.dimlevel - 10) THEN switch DEVICE fog TO on",
            "active": 1
        },
        "humi_night_ok_switch_fog_off": {
            "rule": "IF rfog.state IS on AND ((zeit.hour >= vtimen.dimlevel AND zeit.hour < 24) OR (zeit.hour >= 0 AND zeit.hour < vtimed.dimlevel)) AND humi.humidity >= (vhumin.dimlevel - 10) AND humi.humidity <= (vhumin.dimlevel + 10) THEN switch DEVICE fog TO off",
            "active": 1
        },
        "humi_night_to_high_switch_airair_on": {
            "rule": "IF rfans.state IS on AND ((zeit.hour >= vtimen.dimlevel AND zeit.hour < 24) OR (zeit.hour >= 0 AND zeit.hour < vtimed.dimlevel)) AND humi.humidity != 0 AND humi.humidity > (vhumin.dimlevel + 10) THEN switch DEVICE airair TO on",
            "active": 1
        },
        "humi_and_temp_night_ok_switch_airair_off": {
            "rule": "IF rfans.state IS on AND ((zeit.hour >= vtimen.dimlevel AND zeit.hour < 24) OR (zeit.hour >= 0 AND zeit.hour < vtimed.dimlevel)) AND humi.humidity < (vhumin.dimlevel + 10) AND humi.temperature <= (vtempn.dimlevel + 2) THEN switch DEVICE airair TO off",
            "active": 1
        },
        "temp_night_to_high_switch_airair_on": {
            "rule": "IF rfans.state IS on AND humi.temperature != 0 AND humi.temperature > (vtempn.dimlevel + 2) AND ((zeit.hour >= vtimen.dimlevel AND zeit.hour <= 24) OR (zeit.hour >= 0 AND zeit.hour < vtimed.dimlevel)) AND airair.state IS off THEN switch DEVICE airair TO on",
            "active": 1
        }
    },
    "gui": {
        "humi": {
            "name": "Temperatur / Luftfeuchtigkeit - allgemein",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "templio": {
            "name": "Temperatur Wärmeplatz links",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "tempreo": {
            "name": "Temperatur Wärmeplatz rechts",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "templiu": {
            "name": "Temperatur Schattenplatz links",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "tempreu": {
            "name": "Temperatur Schattenplatz rechts",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "fog": {
            "name": "Zerstäuber",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "airfog": {
            "name": "Lüfter Zerstäuber",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "airair": {
            "name": "Lüfter Frischluft",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "neon": {
            "name": "T5 Neonleuchten",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "spotli": {
            "name": "SPOT Wärmeplatz links",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "spotre": {
            "name": "SPOT Wärmeplatz rechts",
            "group": [ "Terrarium" ],
            "media": [ "all" ]
        },
        "vtempd": {
            "name": "Temperatur TAG °C ( - 2 / + 2 )",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vtempsli": {
            "name": "Temperatur Spot links TAG °C ( - 2 / + 2 )",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vtempsre": {
            "name": "Temperatur Spot rechts TAG °C ( - 2 / + 2 )",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vtempn": {
            "name": "Temperatur NACHT °C ( - 2 / + 2 )",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vhumid": {
            "name": "Luftfeuchtigkeit TAG % ( - 5 / + 5 )",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vhumin": {
            "name": "Luftfeuchtigkeit NACHT % ( - 10 / + 10 )",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vtimed": {
            "name": "Beginn TAG",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "vtimen": {
            "name": "Beginn NACHT",
            "group": [ "Config" ],
            "media": [ "all" ]
        },
        "rlamps": {
            "name": "Lampen automatisch steuern",
            "group": [ "Regeln" ],
            "media": [ "all" ]
        },
        "rfans": {
            "name": "Lüfter automatisch steuern",
            "group": [ "Regeln" ],
            "media": [ "all" ]
        },
        "rfog": {
            "name": "Nebler automatisch steuern",
            "group": [ "Regeln" ],
            "media": [ "all" ]
        }
    },
    "settings": {
        "log-level": 4,
        "pid-file": "/var/run/pilight.pid",
        "log-file": "/var/log/pilight.log",
        "send-repeats": 10,
        "receive-repeats": 1,
        "webserver-enable": 1,
        "webserver-root": "/usr/local/share/pilight/",
        "webserver-port": 5001,
        "webserver-cache": 1,
        "firmware-update": 0
    },
    "hardware": {
        "433gpio": {
            "sender": 0,
            "receiver": 1
        }
    },
    "registry": {
        "webgui": {
            "tabs": 1
        },
        "pilight": {
            "version": {
                "current": "5.0"
            }
        }
    }
}

Changelog

2014-12-17 First version
2014-12-20

  • Integrated generic_dimmers to change all the values on-the-fly without stopping the service and edit config.json
  • First test with disabling rules with a generic_switch.

2014-12-26

  • Rules can be disabled
  • Only temperature controll with stepwise dimming is missing

Published on