diff --git a/layers/dot-cams/ia/layer.js b/layers/511mn/layer.js
similarity index 91%
rename from layers/dot-cams/ia/layer.js
rename to layers/511mn/layer.js
index bf985d2..0f7cfd7 100644
--- a/layers/dot-cams/ia/layer.js
+++ b/layers/511mn/layer.js
@@ -39,7 +39,9 @@ vectorLayer.customPopupCallback = function(feature) {
if (view.category.toLowerCase() == "video") {
const video = document.getElementById('popupVideo');
- const videoSrc = view.sources[0].src;
+ const videoID = view.url.split('/').pop();
+
+ const videoSrc = `https://video.dot.state.mn.us/public/${videoID}.stream/playlist.m3u8`;
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(videoSrc);
diff --git a/layers/dot-cams/ia/pin.svg b/layers/511mn/pin.svg
similarity index 100%
rename from layers/dot-cams/ia/pin.svg
rename to layers/511mn/pin.svg
diff --git a/layers/dot-cams/mn/get_data.py b/layers/511mn/process_data.py
old mode 100755
new mode 100644
similarity index 78%
rename from layers/dot-cams/mn/get_data.py
rename to layers/511mn/process_data.py
index 285171d..4d3bf3e
--- a/layers/dot-cams/mn/get_data.py
+++ b/layers/511mn/process_data.py
@@ -40,17 +40,9 @@ for c in camera_views:
print(c)
raise Exception(f"Unexpected number of features: {len(c['features'])}")
- if re.match(r"Show .* cameras", c['tooltip']):
+ if re.match(r"Show [\d]* cameras", c['tooltip']):
raise Exception(f"Not zoomed in enough! Finding aggregate cameras: {c}")
- for view in c['views']:
- if len(view['sources']) != 1 if view['category'] == 'VIDEO' else 0:
- print(view)
- raise Exception(f"Unexpected number of sources ({len(view['sources'])})")
- for source in view['sources'] or []:
- if source['type'] != 'application/x-mpegURL':
- raise Exception(f"Unexpected type {source['type']}")
-
viewCount += len(c['views'])
cameras.append({
"type": "Feature",
diff --git a/layers/dot-cams/mn/query.graphql b/layers/511mn/query.graphql
similarity index 88%
rename from layers/dot-cams/mn/query.graphql
rename to layers/511mn/query.graphql
index 8c53b14..d032daa 100644
--- a/layers/dot-cams/mn/query.graphql
+++ b/layers/511mn/query.graphql
@@ -18,11 +18,6 @@ query MapFeatures($input: MapFeaturesArgs!, $plowType: String) {
uri
... on CameraView {
url
- sources {
- type
- src
- }
- title
}
category
}
diff --git a/layers/dot-cams/ia/get_data.py b/layers/dot-cams/ia/get_data.py
deleted file mode 100755
index fad76c5..0000000
--- a/layers/dot-cams/ia/get_data.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-
-import requests
-import json
-import re
-
-with open("query.graphql") as f:
- QUERY = f.read()
-
-PAYLOAD = [
- {
- "query": QUERY,
- "variables": {
- "input": {
- # Cover the whole state (this is pretty overkill, admittedly)
- "north":45.2,
- "south":38.2,
- "east":-82.9,
- "west":-98.3,
- "zoom":11,
- "layerSlugs": ["normalCameras"],
- "nonClusterableUris": ["dashboard"]
- },
- "plowType":"plowCameras",
- }
- }
-]
-
-res = requests.post('https://511ia.org/api/graphql', json=PAYLOAD)
-res.raise_for_status()
-
-camera_views = res.json()[0]['data']['mapFeaturesQuery']['mapFeatures']
-
-cameras = []
-
-viewCount = 0
-
-for c in camera_views:
- if len(c['features']) != 1:
- print(c)
- raise Exception(f"Unexpected number of features: {len(c['features'])}")
-
- if re.match(r"Show .* cameras", c['tooltip']):
- raise Exception(f"Not zoomed in enough! Finding aggregate cameras: {c}")
-
- for view in c['views']:
- if len(view['sources']) != 1 if view['category'] == 'VIDEO' else 0:
- print(view)
- raise Exception(f"Unexpected number of sources ({len(view['sources'])})")
- for source in view['sources'] or []:
- if source['type'] != 'application/x-mpegURL':
- raise Exception(f"Unexpected type {source['type']}")
-
- viewCount += len(c['views'])
- cameras.append({
- "type": "Feature",
- "geometry": c['features'][0]['geometry'],
- "properties": {
- 'address': c['tooltip'],
- 'website': c['views'][0]['url'],
- 'originalData': c,
- },
- })
-
-geojson = {
- "type": "FeatureCollection",
- "features": cameras,
-}
-
-with open("data.geojson", "w") as f:
- f.write(json.dumps(geojson))
-
-print(f"{len(cameras)} locations found")
-print(f"{viewCount} total views")
diff --git a/layers/dot-cams/ia/query.graphql b/layers/dot-cams/ia/query.graphql
deleted file mode 100644
index 8c53b14..0000000
--- a/layers/dot-cams/ia/query.graphql
+++ /dev/null
@@ -1,45 +0,0 @@
-query MapFeatures($input: MapFeaturesArgs!, $plowType: String) {
- mapFeaturesQuery(input: $input) {
- mapFeatures {
- bbox
- tooltip
- uri
- features {
- id
- geometry
- properties
- }
- ... on Event {
- priority
- }
- __typename
- ... on Camera {
- views(limit: 5) {
- uri
- ... on CameraView {
- url
- sources {
- type
- src
- }
- title
- }
- category
- }
- }
- ... on Plow {
- views(limit: 5, plowType: $plowType) {
- uri
- ... on PlowCameraView {
- url
- }
- category
- }
- }
- }
- error {
- message
- type
- }
- }
-}
diff --git a/layers/dot-cams/index.js b/layers/dot-cams/index.js
deleted file mode 100644
index ba1a093..0000000
--- a/layers/dot-cams/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import mn from './mn/layer.js';
-import wi from './wi/layer.js';
-import ia from './ia/layer.js';
-
-const dot_cams = {
- name: "State DOT Cameras",
- layers: [
- {
- name: "MNDOT/511MN",
- layer: mn,
- },
- {
- name: "WisDOT/511WI",
- layer: wi,
- },
- {
- name: "Iowa DOT/511IA",
- layer: ia,
- },
- ],
-};
-
-export default dot_cams;
diff --git a/layers/dot-cams/mn/layer.js b/layers/dot-cams/mn/layer.js
deleted file mode 100644
index bf985d2..0000000
--- a/layers/dot-cams/mn/layer.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import VectorLayer from 'ol/layer/Vector';
-import {Vector as VectorSource} from 'ol/source.js';
-import GeoJSON from 'ol/format/GeoJSON.js';
-
-import Hls from 'hls.js';
-
-import {Style} from 'ol/style.js';
-import Icon from 'ol/style/Icon.js';
-
-import url from './data.geojson?url'; // TODO: remove `?url`?
-import pin from './pin.svg?url'; // TODO: remove `?url`?
-
-const vectorLayer = new VectorLayer({
- source: new VectorSource({
- url: url,
- format: new GeoJSON,
- }),
- style: new Style({
- image: new Icon({
- anchor: [0.5, 1],
- src: pin,
- }),
- }),
-});
-
-vectorLayer.customPopup = function(feature) {
- const view = feature.values_.originalData.views[0];
- if (view.category.toLowerCase() == "video") {
- return ``;
- } else if (view.category.toLowerCase() == "image") {
- return `
`;
- } else {
- throw new Exception(`unknown category ${view.category}`);
- }
-};
-
-vectorLayer.customPopupCallback = function(feature) {
- const view = feature.values_.originalData.views[0];
- if (view.category.toLowerCase() == "video") {
- const video = document.getElementById('popupVideo');
-
- const videoSrc = view.sources[0].src;
- if (Hls.isSupported()) {
- var hls = new Hls();
- hls.loadSource(videoSrc);
- hls.attachMedia(video);
- }
- // iDevice support, untested (only works in Safari; required for iPhones)
- else if (video.canPlayType('application/vnd.apple.mpegurl')) {
- video.src = videoSrc;
- }
- }
-}
-
-export default vectorLayer;
diff --git a/layers/dot-cams/mn/pin.svg b/layers/dot-cams/mn/pin.svg
deleted file mode 100644
index fb93212..0000000
--- a/layers/dot-cams/mn/pin.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
diff --git a/layers/dot-cams/wi/get_data.py b/layers/dot-cams/wi/get_data.py
deleted file mode 100644
index c21fb45..0000000
--- a/layers/dot-cams/wi/get_data.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/python3
-
-import requests
-import json
-
-query={
- "columns": [ # no clue what any of this is, so here it stays
- {
- "data": None,
- "name": "",
- },
- {
- "name": "sortId",
- "s": True,
- },
- {
- "name": "region",
- "s": True,
- },
- {
- "name": "county",
- "s": True,
- },
- {
- "name": "roadway",
- "s": True,
- },
- {
- "name": "description1",
- },
- {
- "data": 6,
- "name": "",
- },
- ],
- "start": 0,
- "length": 100,
-}
-
-cameras = []
-available_cameras = 999_999 # lots
-
-while len(cameras) < available_cameras:
- res = requests.get("https://511wi.gov/List/GetData/Cameras", {
- "query": json.dumps(query),
- "lang": "en",
- })
- res.raise_for_status()
- res = res.json()
- available_cameras = res['recordsTotal']
- for c in res['data']:
- cameras.append({
- "type": "Feature",
- "geometry": {
- "type": "Point",
- "coordinates": [c['longitude'], c['latitude']], # yes, [lon, lat] since it's [x, y]
- },
- "properties": {
- 'address': c['displayName'],
- 'website': c['videoUrl'],
- 'originalData': c,
- },
- })
- query['start'] += 100
-
-geojson = {
- "type": "FeatureCollection",
- "features": cameras,
-}
-
-with open("data.geojson", "w") as f:
- f.write(json.dumps(geojson))
-
-print(f"{len(cameras)} locations found")
diff --git a/layers/dot-cams/wi/layer.js b/layers/dot-cams/wi/layer.js
deleted file mode 100644
index 7a8a6e3..0000000
--- a/layers/dot-cams/wi/layer.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import VectorLayer from 'ol/layer/Vector';
-import {Vector as VectorSource} from 'ol/source.js';
-import GeoJSON from 'ol/format/GeoJSON.js';
-
-import Hls from 'hls.js';
-
-import {Style} from 'ol/style.js';
-import Icon from 'ol/style/Icon.js';
-
-import url from './data.geojson?url'; // TODO: remove `?url`?
-import pin from './pin.svg?url'; // TODO: remove `?url`?
-
-const vectorLayer = new VectorLayer({
- source: new VectorSource({
- url: url,
- format: new GeoJSON,
- }),
- style: new Style({
- image: new Icon({
- anchor: [0.5, 1],
- src: pin,
- }),
- }),
-});
-
-vectorLayer.customPopup = function(feature) {
- return ``;
-};
-
-vectorLayer.customPopupCallback = function(feature) {
-
- const video = document.getElementById('popupVideo');
-
- const videoSrc = feature.values_.originalData.videoUrl;
- if (Hls.isSupported()) {
- var hls = new Hls();
- hls.loadSource(videoSrc);
- hls.attachMedia(video);
- }
- // iDevice support, untested (only works in Safari; required for iPhones)
- else if (video.canPlayType('application/vnd.apple.mpegurl')) {
- video.src = videoSrc;
- }
-}
-
-export default vectorLayer;
diff --git a/layers/dot-cams/wi/pin.svg b/layers/dot-cams/wi/pin.svg
deleted file mode 100644
index fb93212..0000000
--- a/layers/dot-cams/wi/pin.svg
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
diff --git a/layers/index.js b/layers/index.js
index 109133c..95999b4 100644
--- a/layers/index.js
+++ b/layers/index.js
@@ -14,7 +14,7 @@ import cellular from './cellular.js';
import light_pollution from './light_pollution.js';
import state_land from './state-land/index.js';
import trips from './trips/index.js';
-import dot_cams from './dot-cams/index.js';
+import _511mncamerasLayer from './511mn/layer.js';
const layerCategories = [
{ // Base maps
@@ -76,9 +76,12 @@ const layerCategories = [
name: "Bikepacking.com Routes",
layer: bikepackingLayer,
},
+ {
+ name: "511MN Cameras",
+ layer: _511mncamerasLayer,
+ }
]
},
- dot_cams,
trips,
chains,
census_bureau,