Skip to content

Commit

Permalink
add preliminary birdnet support
Browse files Browse the repository at this point in the history
  • Loading branch information
Joel Hawksley committed Apr 14, 2024
1 parent 7ce558f commit 41dc63b
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 3 deletions.
35 changes: 35 additions & 0 deletions app/models/birdnet.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class Birdnet
def self.fetch
response = HTTParty.get(Timeframe::Application.config.local["birdnet_url"])

return if response["status"] == "error"

MemoryValue.upsert(
:birdnet,
{
data: response,
last_fetched_at: Time.now.utc.in_time_zone(Timeframe::Application.config.local["timezone"]).to_s
}
)
end

def self.data
MemoryValue.get(:birdnet)[:data] || {}
end

def self.most_unusual_species_trailing_24h
data["species"]&.try(:last) || {}
end

def self.healthy?
return false unless last_fetched_at

DateTime.parse(last_fetched_at) > DateTime.now - 5.minutes
end

# :nocov:
def self.last_fetched_at
MemoryValue.get(:birdnet)[:last_fetched_at]
end
# :nocov
end
13 changes: 10 additions & 3 deletions app/views/displays/mira.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@ div.hide-if-empty style="font-size: 1.75rem; position:absolute; left: 0; right:
strong =< status[:artist]
| :
=< status[:track]
div style="margin-top: 1.5rem; display: flex; justify-content: space-between; line-height: 2rem;"
div style="margin-top: 1.5rem;"
- if Birdnet.healthy? && Birdnet.most_unusual_species_trailing_24h.present?
div style="text-align: right; margin-bottom: .5rem;"
i.fa-solid.fa-crow
=< Birdnet.most_unusual_species_trailing_24h["commonName"]
div style="display: flex; justify-content: space-between; line-height: 2rem;"
div style="font-size: 1.75rem"
- if HomeAssistantHome.package_present?
i.fa-solid.fa-box-open style="margin-right: 1rem"
Expand All @@ -55,10 +60,12 @@ div style="margin-top: 1.5rem; display: flex; justify-content: space-between; li
i.fa-solid.fa-house-circle-exclamation style="margin-right: 1rem"
- if !HomeAssistantHome.hot_water_heater_healthy?
i.fa-solid.fa-tank-water style="margin-right: 1rem"
- if !Birdnet.healthy?
i.fa-solid.fa-microphone-slash style="margin-right: 1rem"
div style="font-size:2rem;" = DateTime.now.strftime("%A, %B %-d")
div style="margin-top: 1rem; display: flex; justify-content: space-between; line-height: .7"
div style="font-size: 5.5rem;; margin-bottom: 1rem;" = view_object[:current_temperature]
div style="font-size: 5.5rem; margin-bottom: 1rem;" = view_object[:current_temperature]
div style="text-align: right; font-size: 5.5rem;" = DateTime.now.strftime("%l:%M%P")
hr style="margin: 1rem 0 1rem; border: none; background-color: #ccc; color: #ccc; height: 2px;"
div style="position: absolute; top: 11.5rem; bottom: 0; left: 2rem; right: 2rem; overflow: hidden;"
div style="position: absolute; top: 12.5rem; bottom: 0; left: 2rem; right: 2rem; overflow: hidden;"
= render Timeline.new(view_object: view_object)
1 change: 1 addition & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def run_in_bg(interval, &block)
GoogleAccount.all.each(&:fetch)
end
end
run_in_bg(300) { Birdnet.fetch }
end
end
# :nocov:
Expand Down
98 changes: 98 additions & 0 deletions test/models/birdnet_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# frozen_string_literal: true

require "test_helper"

class BirdnetTest < Minitest::Test
include ActiveSupport::Testing::TimeHelpers

def test_fetch
VCR.use_cassette(:birdnet_fetch, match_requests_on: [:method]) do
Birdnet.fetch
end

MemoryValue.upsert(:birdnet, {})
end

def test_health_no_data
Birdnet.stub :last_fetched_at, nil do
assert(!Birdnet.healthy?)
end
end

def test_health_current_data
Birdnet.stub :last_fetched_at, "2023-08-27 15:14:59 -0600" do
travel_to DateTime.new(2023, 8, 27, 15, 15, 0, "-0600") do
assert(Birdnet.healthy?)
end
end
end

def test_health_stale_data
Birdnet.stub :last_fetched_at, "2023-08-27 15:14:59 -0600" do
travel_to DateTime.new(2023, 8, 27, 16, 20, 0, "-0600") do
refute(Birdnet.healthy?)
end
end
end

def test_most_unusual_species_trailing_24h_no_data
assert_equal(Birdnet.most_unusual_species_trailing_24h, {})
end

def test_most_unusual_species_trailing_24h
data = { "species" => [{"id"=>134,
"commonName"=>"House Finch",
"scientificName"=>"Haemorhous mexicanus",
"color"=>"#ff5a86",
"imageUrl"=>
"https://media.birdweather.com/species/134/HouseFinch-standard-3329463dada4a864431241d37400ba54.jpg",
"thumbnailUrl"=>
"https://media.birdweather.com/species/134/HouseFinch-thumbnail-ea7d4c693d0ac395d440407b51951f22.jpg",
"detections"=>{"total"=>103, "almostCertain"=>103, "veryLikely"=>0, "uncertain"=>0, "unlikely"=>0},
"latestDetectionAt"=>"2024-04-13T19:16:35.000-06:00"},
{"id"=>28,
"commonName"=>"Townsend's Solitaire",
"scientificName"=>"Myadestes townsendi",
"color"=>"#00a842",
"imageUrl"=>
"https://media.birdweather.com/species/28/TownsendsSolitaire-standard-d37b6e043b4eed13817adc83cd476a15.jpg",
"thumbnailUrl"=>
"https://media.birdweather.com/species/28/TownsendsSolitaire-thumbnail-fe60cb6923339361e1eecf90773786da.jpg",
"detections"=>{"total"=>3, "almostCertain"=>3, "veryLikely"=>0, "uncertain"=>0, "unlikely"=>0},
"latestDetectionAt"=>"2024-04-13T18:51:02.000-06:00"},
{"id"=>60,
"commonName"=>"Rock Pigeon",
"scientificName"=>"Columba livia",
"color"=>"#8ed96e",
"imageUrl"=>
"https://media.birdweather.com/species/60/RockPigeon-standard-e442656b8173c4956bc4ef5fdd1a7e53.jpg",
"thumbnailUrl"=>
"https://media.birdweather.com/species/60/RockPigeon-thumbnail-a43e71081b432231e10a1774b5735053.jpg",
"detections"=>{"total"=>3, "almostCertain"=>3, "veryLikely"=>0, "uncertain"=>0, "unlikely"=>0},
"latestDetectionAt"=>"2024-04-13T20:09:35.000-06:00"},
{"id"=>65,
"commonName"=>"Northern Flicker",
"scientificName"=>"Colaptes auratus",
"color"=>"#ff6ad7",
"imageUrl"=>
"https://media.birdweather.com/species/65/NorthernFlicker-standard-981bd7e4c13509e1db15ba936807ddb4.jpg",
"thumbnailUrl"=>
"https://media.birdweather.com/species/65/NorthernFlicker-thumbnail-7e0c055da080666c647db31e799f9ed9.jpg",
"detections"=>{"total"=>2, "almostCertain"=>2, "veryLikely"=>0, "uncertain"=>0, "unlikely"=>0},
"latestDetectionAt"=>"2024-04-13T18:33:17.000-06:00"},
{"id"=>568,
"commonName"=>"Western Meadowlark",
"scientificName"=>"Sturnella neglecta",
"color"=>"#8c9e00",
"imageUrl"=>
"https://media.birdweather.com/species/568/WesternMeadowlark-standard-cf1c86d78827eccc53bb0337bdacca0c.jpg",
"thumbnailUrl"=>
"https://media.birdweather.com/species/568/WesternMeadowlark-thumbnail-c0f44fda850bcdd76811e2761c64c4b9.jpg",
"detections"=>{"total"=>2, "almostCertain"=>2, "veryLikely"=>0, "uncertain"=>0, "unlikely"=>0},
"latestDetectionAt"=>"2024-04-13T16:10:08.000-06:00"}] }

Birdnet.stub :data, data do
assert_equal(568, Birdnet.most_unusual_species_trailing_24h["id"])
end
end
end
52 changes: 52 additions & 0 deletions test/vcr_cassettes/birdnet_fetch.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 41dc63b

Please sign in to comment.