My Gate Warning System: YoLink, Home Assistant, and Keeping the Cows Where They Belong

If you have more than one gate going into a pasture, you already know the problem. You pull through Gate A with a tractor or a side-by-side, do whatever needs doing, drive out through Gate B, and completely forget that Gate A is sitting wide open. It’s not a big deal right up until you look out the window and see a cow taking a casual stroll down your driveway.

To keep the livestock where they actually belong, I built a remote gate monitoring setup for the main gate that sits about 300 yards up the driveway from the house. I picked up the YoLink LoRa Smart Outdoor Contact Sensor & Hub Starter Kit for $50 to get rolling. That makes expanding pretty painless, since individual add-on sensors are only around $25 each. Coupled with some PVC pipe and Home Assistant, it pushes real-time alerts through ntfy when the main gate is left open.

Smartphone lock screen displaying ntfy push notifications for cattle gate monitor status updates while having lunch 200 miles away from home.
Receiving real-time gate state alerts via ntfy while eating lunch 200 miles from home.

The Physical Build: Sun-Proofing for Texas Heat

The YoLink contact sensor is technically rated as weatherproof, but it comes in a black plastic housing. Under the intense Texas sun, a black enclosure mounted out in the open will bake in high ambient heat, degrade under UV exposure, and quickly kill the internal batteries.

To keep the hardware alive without spending commercial-grade money, I built some enclosures out of PVC pipe and hose clamps near the hinge end of the gate.

  • The Sensor Housing: The YoLink sensor lives inside a length of 2-inch PVC pipe to act as a thermal and UV shield split with a coupler in the middle . The top piece of pipe is glued into the coupler, while the bottom piece of pipe slides into the lower end of the coupler unglued. Because the bottom pipe sits inside and underneath the lip of the coupler, rain sheds down the outside without running into the bottom half. It stays completely dry inside, but pops right out when it is time to swap batteries. The whole assembly is fastened to the gate frame with heavy-duty hose clamps.
  • The Custom Magnet: The weak little magnet that comes in the box wasn’t going to cut it across a wide pasture gate gap. I stacked a handful of strong ceramic magnets inside a 1-inch PVC pipe with an elbow and end cap on each side to keep them weatherproof. That assembly is hose-clamped directly to the threaded steel hinge pin bolted into the post.
  • The Long Haul (LoRa): At 300 yards through open air, trees, and weather, Wi-Fi and Zigbee are completely out of the question. YoLink’s LoRa signal sits steadily around -93 dBm back to the hub inside the house, providing plenty of “link margin” to guarantee state changes actually land without needing a repeater.
YoLink outdoor contact sensor housed inside a 2-inch PVC pipe mounted to a metal cattle gate frame with hose clamps.
2-inch PVC housing protecting the YoLink sensor from Texas sun and rain.

The Automation Philosophy: Day vs. Night

Notifications are only useful if you don’t grow blind to them. If your phone chirps every single time someone opens the gate during the day to run equipment, you’re just going to swipe it away and ignore it.

The Home Assistant logic keeps this from happening by breaking it down into two core functions:

  1. Daytime Routine (6 AM – 10 PM): During the day, people are expected to be going in and out. The system stays completely quiet when the gate first opens. It only speaks up if the gate stays continuously open for 15 minutes (a gentle reminder) and then escalates at 30 minutes (a “go double-check the latch” alert), provided the Work Snooze toggle is off.
  2. Nighttime Routine (10 PM – 6 AM): At 2:00 AM, nobody should be messing with the pasture gate. The moment the contact sensor opens at night, it bypasses all delays and fires an immediate Priority 5 Critical Intrusion Alert. It uses ntfy to break through Do Not Disturb and ding the phone instantly.

The Alert Engine: Clean ntfy Integration

Instead of relying on standard app push notifications, Home Assistant sends HTTP POST requests directly to the ntfy REST API via rest_command.

By pushing parameters like Title, Priority, and Tags straight into the HTTP headers rather than formatting them in the JSON body, the notifications hit your phone cleanly without weird URL encoding or random + signs sandwiched between every word.

The YAML Package

Drop this single file into your Home Assistant packages/ directory to pull in the REST command and all three automation routines at once.

YAML

###############################################################################
# Package: Cattle Gate Monitoring System
# Topic: Home-random-id
###############################################################################

# -----------------------------------------------------------------------------
# REST Command (Sends headers directly to ntfy API)
# -----------------------------------------------------------------------------
rest_command:
  ntfy_cattle_gate:
    url: "https://ntfy.sh/Home-random-id"
    method: POST
    headers:
      Title: "{{ title | default('') }}"
      Priority: "{{ priority | default(3) }}"
      Tags: "{{ tags | default([]) | join(',') }}"
    payload: "{{ message }}"

# -----------------------------------------------------------------------------
# Automations
# -----------------------------------------------------------------------------
automation:
  # ---------------------------------------------------------------------------
  # 1. Immediate Night Intrusion Alert (10 PM - 6 AM)
  # Trigger: Instantly on opening
  # ---------------------------------------------------------------------------
  - id: cattle_gate_night_intrusion
    alias: "Cattle Gate: Night Intrusion Alert"
    mode: single
    trigger:
      - platform: state
        entity_id: binary_sensor.gate_sensor_door
        to: "on"
    condition:
      - condition: time
        after: "22:00:00"
        before: "06:00:00"
    action:
      - action: rest_command.ntfy_cattle_gate
        data:
          title: "INTRUSION: GATE OPENED AT NIGHT"
          message: "The cattle gate was opened at {{ now().strftime('%H:%M') }}!"
          priority: 5
          tags: ["warning", "rotating_light"]

  # ---------------------------------------------------------------------------
  # 2. Daytime Left Open Warning & Escalation (6 AM - 10 PM)
  # Trigger: Gate stays open continuously for 15 minutes
  # Priority: Default (3) at 15m, High (4) at 30m
  # ---------------------------------------------------------------------------
  - id: cattle_gate_daytime_warning
    alias: "Cattle Gate: Daytime Left Open Warning"
    mode: restart
    trigger:
      - platform: state
        entity_id: binary_sensor.gate_sensor_door
        to: "on"
        for:
          minutes: 15
    condition:
      - condition: time
        after: "06:00:00"
        before: "22:00:00"
    action:
      # 15 Minute Warning
      - action: rest_command.ntfy_cattle_gate
        data:
          title: "Gate Open Reminder"
          message: "Cattle gate has been open for 15 minutes."
          priority: 3
          tags: ["door", "cow"]

      # Wait another 15 minutes (30 Minutes total open time)
      - delay:
          minutes: 15

      # Re-verify gate is still open
      - condition: state
        entity_id: binary_sensor.gate_sensor_door
        state: "on"

      # 30 Minute Escalation
      - action: rest_command.ntfy_cattle_gate
        data:
          title: "ALERT: Gate Open 30+ Minutes"
          message: "The cattle gate has been left open for 30 minutes! Please verify it is latched."
          priority: 4
          tags: ["warning", "cow"]

  # ---------------------------------------------------------------------------
  # 3. Auto-Clear Notification (Gate Closed)
  # Trigger: Gate returns to 'off' (Closed)
  # ---------------------------------------------------------------------------
  - id: cattle_gate_auto_clear
    alias: "Cattle Gate: Auto-Clear On Close"
    mode: single
    trigger:
      - platform: state
        entity_id: binary_sensor.gate_sensor_door
        from: "on"
        to: "off"
    action:
      # Send a low-priority notification acknowledging closure
      - action: rest_command.ntfy_cattle_gate
        data:
          title: "Gate Closed"
          message: "Cattle gate is secured."
          priority: 2
          tags: ["heavy_check_mark"]

Final Thoughts

At the end of the day, a setup like this is about applying cheap, reliable technology to eliminate human error. Folks get to focus on working the property, I don’t get a bunch of useless spam alerts blowing up my phone while work is going on, and I get peace of mind knowing the cows aren’t going to end up in the front yard at 2:00 AM. Since I live right out here on the property, I’m the one getting the actual alerts and can just head out to throw the latch myself if someone forgets to close it up.

For around $50 in hardware and a few dollars in PVC fittings, it’s one of those homelab-meets-farm projects that pays for itself the very first time it catches a gate left unlatched.

While You’re Here…

If you enjoyed this project, check out a few other ways I’m leveraging Home Assistant around the property and on the road in our camper:

Share Our Stories

Leave a Reply

Your email address will not be published. Required fields are marked *