mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-02-04 18:36:00 -05:00
populate timeZoneName as expected by UI
This works by a nasty hack, but it seems to work well enough for now. Fingers crossed.
This commit is contained in:
parent
2966cf59b0
commit
8de7e391f8
@ -42,6 +42,11 @@ use tokio_core::reactor;
|
|||||||
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};
|
use tokio_signal::unix::{Signal, SIGINT, SIGTERM};
|
||||||
use web;
|
use web;
|
||||||
|
|
||||||
|
// These are used in a hack to get the name of the current time zone (e.g. America/Los_Angeles).
|
||||||
|
// They seem to be correct for Linux and OS X at least.
|
||||||
|
const LOCALTIME_PATH: &'static str = "/etc/localtime";
|
||||||
|
const ZONEINFO_PATH: &'static str = "/usr/share/zoneinfo/";
|
||||||
|
|
||||||
const USAGE: &'static str = r#"
|
const USAGE: &'static str = r#"
|
||||||
Usage: moonfire-nvr run [options]
|
Usage: moonfire-nvr run [options]
|
||||||
|
|
||||||
@ -77,6 +82,16 @@ fn setup_shutdown_future(h: &reactor::Handle) -> Box<Future<Item = (), Error = (
|
|||||||
.map_err(|_| ()))
|
.map_err(|_| ()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resolve_zone() -> String {
|
||||||
|
let p = ::std::fs::read_link(LOCALTIME_PATH).expect("unable to read localtime symlink");
|
||||||
|
let p = p.to_str().expect("localtime symlink destination must be valid UTF-8");
|
||||||
|
if !p.starts_with(ZONEINFO_PATH) {
|
||||||
|
panic!("Expected {} to point to a path within {}; actually points to {}",
|
||||||
|
LOCALTIME_PATH, ZONEINFO_PATH, p);
|
||||||
|
}
|
||||||
|
p[ZONEINFO_PATH.len()..].into()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run() -> Result<(), Error> {
|
pub fn run() -> Result<(), Error> {
|
||||||
let args: Args = super::parse_args(USAGE)?;
|
let args: Args = super::parse_args(USAGE)?;
|
||||||
let (_db_dir, conn) = super::open_conn(
|
let (_db_dir, conn) = super::open_conn(
|
||||||
@ -86,7 +101,7 @@ pub fn run() -> Result<(), Error> {
|
|||||||
let dir = dir::SampleFileDir::new(&args.flag_sample_file_dir, db.clone()).unwrap();
|
let dir = dir::SampleFileDir::new(&args.flag_sample_file_dir, db.clone()).unwrap();
|
||||||
info!("Database is loaded.");
|
info!("Database is loaded.");
|
||||||
|
|
||||||
let s = web::Service::new(db.clone(), dir.clone(), Some(&args.flag_ui_dir))?;
|
let s = web::Service::new(db.clone(), dir.clone(), Some(&args.flag_ui_dir), resolve_zone())?;
|
||||||
|
|
||||||
// Start a streamer for each camera.
|
// Start a streamer for each camera.
|
||||||
let shutdown_streamers = Arc::new(AtomicBool::new(false));
|
let shutdown_streamers = Arc::new(AtomicBool::new(false));
|
||||||
|
12
src/json.rs
12
src/json.rs
@ -34,10 +34,13 @@ use std::collections::BTreeMap;
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct ListCameras<'a> {
|
#[serde(rename_all="camelCase")]
|
||||||
|
pub struct TopLevel<'a> {
|
||||||
|
pub time_zone_name: &'a str,
|
||||||
|
|
||||||
// Use a custom serializer which presents the map's values as a sequence and includes the
|
// Use a custom serializer which presents the map's values as a sequence and includes the
|
||||||
// "days" attribute or not, according to the bool in the tuple.
|
// "days" attribute or not, according to the bool in the tuple.
|
||||||
#[serde(serialize_with = "ListCameras::serialize_cameras")]
|
#[serde(serialize_with = "TopLevel::serialize_cameras")]
|
||||||
pub cameras: (&'a BTreeMap<i32, db::Camera>, bool),
|
pub cameras: (&'a BTreeMap<i32, db::Camera>, bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +107,8 @@ struct CameraDayValue {
|
|||||||
pub total_duration_90k: i64,
|
pub total_duration_90k: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ListCameras<'a> {
|
impl<'a> TopLevel<'a> {
|
||||||
/// Serializes cameras as a list (rather than a map), wrapping each camera in the
|
/// Serializes cameras as a list (rather than a map), optionally including the `days` field.
|
||||||
/// `ListCamerasCamera` type to tweak the data returned.
|
|
||||||
fn serialize_cameras<S>(cameras: &(&BTreeMap<i32, db::Camera>, bool),
|
fn serialize_cameras<S>(cameras: &(&BTreeMap<i32, db::Camera>, bool),
|
||||||
serializer: S) -> Result<S::Ok, S::Error>
|
serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
|
@ -172,6 +172,7 @@ struct ServiceInner {
|
|||||||
dir: Arc<SampleFileDir>,
|
dir: Arc<SampleFileDir>,
|
||||||
ui_files: HashMap<String, UiFile>,
|
ui_files: HashMap<String, UiFile>,
|
||||||
pool: futures_cpupool::CpuPool,
|
pool: futures_cpupool::CpuPool,
|
||||||
|
time_zone_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceInner {
|
impl ServiceInner {
|
||||||
@ -197,7 +198,10 @@ impl ServiceInner {
|
|||||||
|
|
||||||
let buf = {
|
let buf = {
|
||||||
let db = self.db.lock();
|
let db = self.db.lock();
|
||||||
serde_json::to_vec(&json::ListCameras{cameras: (db.cameras_by_id(), days)})?
|
serde_json::to_vec(&json::TopLevel {
|
||||||
|
time_zone_name: &self.time_zone_name,
|
||||||
|
cameras: (db.cameras_by_id(), days),
|
||||||
|
})?
|
||||||
};
|
};
|
||||||
let len = buf.len();
|
let len = buf.len();
|
||||||
let body: slices::Body = Box::new(stream::once(Ok(ARefs::new(buf))));
|
let body: slices::Body = Box::new(stream::once(Ok(ARefs::new(buf))));
|
||||||
@ -390,7 +394,7 @@ impl ServiceInner {
|
|||||||
pub struct Service(Arc<ServiceInner>);
|
pub struct Service(Arc<ServiceInner>);
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
pub fn new(db: Arc<db::Database>, dir: Arc<SampleFileDir>, ui_dir: Option<&str>)
|
pub fn new(db: Arc<db::Database>, dir: Arc<SampleFileDir>, ui_dir: Option<&str>, zone: String)
|
||||||
-> Result<Self, Error> {
|
-> Result<Self, Error> {
|
||||||
let mut ui_files = HashMap::new();
|
let mut ui_files = HashMap::new();
|
||||||
if let Some(d) = ui_dir {
|
if let Some(d) = ui_dir {
|
||||||
@ -402,6 +406,7 @@ impl Service {
|
|||||||
dir,
|
dir,
|
||||||
ui_files,
|
ui_files,
|
||||||
pool: futures_cpupool::Builder::new().pool_size(1).name_prefix("static").create(),
|
pool: futures_cpupool::Builder::new().pool_size(1).name_prefix("static").create(),
|
||||||
|
time_zone_name: zone,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user