-
Notifications
You must be signed in to change notification settings - Fork 52
Administration guide
Orcasite is deployed (as of late 2018) via the Heroku Git (use heroku CLI = command line interface). Each Heroku app (for live, beta, and dev.orcasound.net) has a distinct Postgres database and host URL.
The databases have an evolving number of tables. As of September 2023 they include:
- feeds - one live feed for each hydrophone location
- detections - a new detection is created when a human listener indicates they hear something interesting
- candidates - a new candidate is defined when a new detection occurs more than 3 min after a previous candidate’s last detection
- users - users are initially network admins and moderators, but may have other roles (e.g. hydrophone host organization)
- subscribers - are entities who would like to subscribe to some type of notification
- subscriptions - options for subscribers include emails upon 2 types of events: new human detection, and/or candidate confirmed by a moderator
- notifications - communication events with subscribers via subscriptions
As of orcasite
UI version 3, a GraphiQL playground has been implemented at live.orcasound.net/graphiql. (Thanks, Skander!) Below are a couple screenshots of the playground and current data schemes, as well as some sample queries.
** The playground in v3 **
** Example data Schema view **
Here are some handy links for learning more, and then some example queries:
- GraphiQL on Github (pronounced "Graphical", i.e. /ˈɡrafək(ə)l/ )
- GraphiQL tutorial by ScienceLogic
query {
feeds {
name
slug
location_point
}
}
query {
candidates {
count
}
}
Returns 3989
on 12/1/2023; 4373
on 2/10/24.
query {
detections {
count
}
}
Returns 7062
on 12/1/2023; 7655
on 2/10/24.
{
detections (limit: 5, filter: {category: {eq: WHALE}} ) {
results {
timestamp
description
feed {
slug
}
}
}
}
Returns this on 2/10/24 at 00:30 Pacific:
From Skander to Adrian in Zulip post on 1/14/2025:
Here's an example of a query you can run to retrieve the audio data segments available for a particular hydrophone location (identified by its feed slug
value) between a start datetime and an end datetime (specified within the GMT time zone).
{
feedSegments(
filter: {
startTime: { greaterThanOrEqual: "2024-12-03T23:46:38.760957Z" }
endTime: { lessThanOrEqual: "2024-12-03T23:56:38.760957Z" }
feed: { slug: { eq: "orcasound-lab" } }
}
sort: { field: START_TIME, order: DESC }
limit: 5
) {
results {
startTime
endTime
duration
bucket
bucketRegion
cloudfrontUrl
fileName
playlistM3u8Path
playlistPath
playlistTimestamp
segmentPath
feedId
}
}
}
Timestamps are in UTC, and the feed slugs can be found with their own query:
{
feeds {
id
slug
}
}
After testing your queries in the playground, you may want to access information from Orcasound's databases programmatically (e.g. using CuRL or pyCurl), or in another app like Postman.com . It may be helpful to peruse the Orcasound API documentation: Swagger | Redoc
Here's syntax that worked for the Orcasound's API (as of 11/1/2024) in a Postman POST:
POST https://live.orcasound.net/graphql
And a curl
query
curl -s https://live.orcasound.net/api/json/feeds
As a (related aside): here's syntax that worked for the OrcaHello API (as of 11/1/2024) in a Postman and curl
GET query:
GET https://aifororcasdetections.azurewebsites.net/api/detections
curl -X GET https://aifororcasdetections.azurewebsites.net/api/detections
Each hydrophone location is a node in the physical network. Within a deployed version of orcasite, the node represented by a row in the feeds
table. That table is part of this Postgres database schema (as of 2022):
For example, the feeds
table as of 5/5/2022 (with three hydrophone locations in Washington State) looks like this:
Here's a description of the 7 fields in the feeds
table:
-
id
= a unique index associated with this row in the table -
name
= A human readable description of the location. In v2 this text string is used to populate the drop-down feed list. -
node_name
= a string with formatdevice_location_name
that uniquely identifies the location within the S3 buckets used to store audio data from this location. Note thatrpi
stands for Raspberry Pi, the device type currently running at each Orcasound location. Sometimes node_name is also used to organize other content for the node, like text and images in theorcasite
S3 bucket used within each feed page of the v2 UI. -
slug
= a string used at the end oflive.orcasound.net
orbeta.orcasound.net
to complete the URL of a given feed page, e.g.https://live.orcasound.net/orcasound-lab
-
inserted_at
= a timestamp when the row was created -
updated_at
= a timestamp when the row was updated most recently -
location_point
= the latitude and longitude of the node location, encoded in Well Known Binary format
So, as an example, to add a new node at Sunset Bay (between Mukilteo and Edmonds in Puget Sound), you will need the following fields and values:
-
name
= Sunset Bay -
node_name
= rpi_sunset_bay -
slug
= sunset-bay -
location_point
= 010100000073f757355f955ec09b50246fb7ee4740 (based entering the Well Known Text = WKTPOINT(-122.33393605795372 47.86497296593844)
into this handy WKB-point converter site
Last update 8/13/24 live nodes (via the "View production feeds" Graphiql query executed at live.orcasound.net/graphiql)
{
"data": {
"feeds": [
{
"location_point": {
"coordinates": [
-123.058779,
48.591294
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "North San Juan Channel",
"slug": "north-sjc"
},
{
"location_point": {
"coordinates": [
-122.6040035,
48.0336664
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "Bush Point",
"slug": "bush-point"
},
{
"location_point": {
"coordinates": [
-122.33393605795372,
47.86497296593844
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "Beach Camp at Sunset Bay",
"slug": "sunset-bay"
},
{
"location_point": {
"coordinates": [
-123.1735774,
48.5583362
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "Orcasound Lab",
"slug": "orcasound-lab"
},
{
"location_point": {
"coordinates": [
-122.760614,
48.135743
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "Port Townsend",
"slug": "port-townsend"
}
]
}
}
Last update 8/13/24 for beta nodes (via the "View production feeds" Graphiql query executed at beta.orcasound.net/graphiql)
"data": {
"feeds": [
{
"location_point": {
"coordinates": [
-122.37267,
47.388383
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "Point Robinson",
"slug": "point-robinson"
},
{
"location_point": {
"coordinates": [
-122.32512,
47.34922
],
"crs": {
"properties": {
"name": "EPSG:4326"
},
"type": "name"
},
"type": "Point"
},
"name": "MaST Center Aquarium",
"slug": "mast-center"
}
]
}
}
Currently (May 2022), the only way to add a new feed is by manually connecting to the running app. First, you need to have installed the Heroku CLI. After logging in with the CLI, you can connect to the Elixir interactive shell (IEx) by running:
heroku run POOL_SIZE=2 iex -S mix -a orcasite
In this case we're connecting directly to the production app (orcasite) but we could easily connect to another app (e.g. orcasite-beta):
heroku run POOL_SIZE=2 iex -S mix -a orcasite-beta
Once IEx is up and running you should see something like this
From here, we'll use Ecto to directly make changes to the database (be careful!). Entering the following will create a new entry in the database for the Sunset Bay hydrophone.
alias Orcasite.Repo
alias Orcasite.Radio.Feed
feed = %Feed{
location_point: Geo.WKT.decode!("SRID=4326;POINT(-122.33393605795372 47.86497296593844)"),
name: "Sunset Bay",
node_name: "rpi_sunset_bay",
slug: "sunset-bay"
}
Repo.insert!(feed)
We're done! The new feed should show up in the database and on the site. Don't forget to update S3 bucket with the HTML content and images, and of course, make sure the node is streaming to the streaming-orcasound-net
bucket.
-
Review reports from Orcasound listeners (while authenticated and approved as a moderator)
-
Listen to the candidate event until you are 100% sure the listener heard a whale.
-
Select the NOTIFY SUBSCRIBERS button (in gray on right side of the screenshot below), if all these conditions are met:
3a. the signal to noise ratio is currently good enough for an exciting and compelling live-listening session;
3b. you believe that the acoustic event is likely to continue for at least 5-10 more minutes (e.g. the signals are not rapidly fading out); and,
3c. you expect noise levels to not increase rapidly during the event (e.g. you've checked for approaching vessels via vesseltraffic.com
- In the modal, add some text that will customize the top header within the email template. For example, type
Southern Resident Killer Whales are currently being heard near the Sunset Bay hydrophones in north Puget Sound (between Edmonds and Mukilteo)!
and you'll get this type of result:
- Select the
SUBMIT
button. - If you want to cancel the sending of your notification, select the
CANCEL
button. - If you so desire, watch the progress of your notification sending process. It is throttled to 14 sends/s to stay below AWS SES low-cost threshold, so for a list of ~4000 subscribers it will take about 5 minutes.
Associated resources:
Current template (Feb 2024)
One mjml editor: (https://mjml.io/try-it-live) and some other options as well (desktop app, vs code extension).
Another mjml wysiwyg editor: https://grapesjs.com/demo-mjml.html