-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modeled Coverage - Phase 3 #559
Changes from 43 commits
0479b5f
498685e
bab457f
60814f7
e52dc60
e35ee73
7e04c77
54bcaed
ca0434d
da1ccb2
8a1e2a6
57da60b
ba97a7e
74d6eb8
64fa0b3
8c52ceb
a1c254d
6619bfd
99505a3
6b5c69e
035e4a9
242ad5a
349a92e
567bd35
a5c9d4d
9d1dffb
0f5cd3d
cb0ae3c
d886af8
5cd1b75
fee3eb3
e35c82b
985c990
d066c29
a71a601
1deea42
9c88a27
45638d5
8201e1b
9301ad7
b8b719b
eccb3f5
c2827a8
83f0ce6
12b9c96
e288a10
cf76f30
25d787a
34057e7
9ec0f69
9b38ab4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use crate::{ | ||
error::DecodeError, | ||
traits::{MsgDecode, TimestampDecode}, | ||
Error, Result, | ||
}; | ||
use chrono::{DateTime, Utc}; | ||
use helium_crypto::PublicKeyBinary; | ||
use helium_proto::services::poc_mobile::{ | ||
CoverageObjectIngestReportV1, CoverageObjectReqV1, | ||
RadioHexSignalLevel as RadioHexSignalLevelProto, SignalLevel, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
use uuid::Uuid; | ||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||
pub struct RadioHexSignalLevel { | ||
pub location: h3o::CellIndex, | ||
pub signal_level: SignalLevel, | ||
pub signal_power: i32, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||
pub struct CoverageObject { | ||
pub pub_key: PublicKeyBinary, | ||
pub uuid: Uuid, | ||
pub cbsd_id: String, | ||
pub coverage_claim_time: DateTime<Utc>, | ||
pub indoor: bool, | ||
pub coverage: Vec<RadioHexSignalLevel>, | ||
pub signature: Vec<u8>, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||
pub struct CoverageObjectIngestReport { | ||
pub received_timestamp: DateTime<Utc>, | ||
pub report: CoverageObject, | ||
} | ||
|
||
impl MsgDecode for CoverageObject { | ||
type Msg = CoverageObjectReqV1; | ||
} | ||
|
||
impl MsgDecode for CoverageObjectIngestReport { | ||
type Msg = CoverageObjectIngestReportV1; | ||
} | ||
|
||
impl TryFrom<CoverageObjectIngestReportV1> for CoverageObjectIngestReport { | ||
type Error = Error; | ||
|
||
fn try_from(v: CoverageObjectIngestReportV1) -> Result<Self> { | ||
Ok(Self { | ||
received_timestamp: v.received_timestamp.to_timestamp_millis()?, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any reason not to implement the MsgTimestamp trait to handle these timestamps here and in subsequent msgs below ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eh, just didn't see a reason to implement it to only be used one other place There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think its a matter of convention and ensuring consistency. |
||
report: v | ||
.report | ||
.ok_or_else(|| Error::not_found("ingest coverage object report"))? | ||
.try_into()?, | ||
}) | ||
} | ||
} | ||
|
||
impl TryFrom<CoverageObjectReqV1> for CoverageObject { | ||
type Error = Error; | ||
|
||
fn try_from(v: CoverageObjectReqV1) -> Result<Self> { | ||
let coverage: Result<Vec<RadioHexSignalLevel>> = v | ||
.coverage | ||
.into_iter() | ||
.map(RadioHexSignalLevel::try_from) | ||
.collect(); | ||
Ok(Self { | ||
pub_key: v.pub_key.into(), | ||
uuid: Uuid::from_slice(&v.uuid).map_err(DecodeError::from)?, | ||
cbsd_id: v.cbsd_id, | ||
coverage_claim_time: v.coverage_claim_time.to_timestamp()?, | ||
indoor: v.indoor, | ||
coverage: coverage?, | ||
signature: v.signature, | ||
}) | ||
} | ||
} | ||
|
||
impl TryFrom<RadioHexSignalLevelProto> for RadioHexSignalLevel { | ||
type Error = Error; | ||
|
||
fn try_from(v: RadioHexSignalLevelProto) -> Result<Self> { | ||
Ok(Self { | ||
signal_level: SignalLevel::from_i32(v.signal_level).ok_or_else(|| { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This just happens to be the pattern I see everywhere else in the file store |
||
DecodeError::unsupported_signal_level("coverage_object_req_v1", v.signal_level) | ||
})?, | ||
signal_power: v.signal_power, | ||
location: v.location.parse().map_err(DecodeError::from)?, | ||
}) | ||
} | ||
} | ||
|
||
impl From<RadioHexSignalLevel> for RadioHexSignalLevelProto { | ||
fn from(rhsl: RadioHexSignalLevel) -> RadioHexSignalLevelProto { | ||
RadioHexSignalLevelProto { | ||
signal_level: rhsl.signal_level as i32, | ||
signal_power: rhsl.signal_power, | ||
location: rhsl.location.to_string(), | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -6,6 +6,7 @@ use chrono::{DateTime, Utc}; | |||||
use helium_crypto::PublicKeyBinary; | ||||||
use helium_proto::services::poc_mobile::{CellHeartbeatIngestReportV1, CellHeartbeatReqV1}; | ||||||
use serde::{Deserialize, Serialize}; | ||||||
use uuid::Uuid; | ||||||
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||||||
pub struct CellHeartbeat { | ||||||
|
@@ -18,6 +19,13 @@ pub struct CellHeartbeat { | |||||
pub operation_mode: bool, | ||||||
pub cbsd_category: String, | ||||||
pub cbsd_id: String, | ||||||
pub coverage_object: Vec<u8>, | ||||||
} | ||||||
|
||||||
impl CellHeartbeat { | ||||||
pub fn coverage_object(&self) -> Option<Uuid> { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
Uuid::from_slice(&self.coverage_object).ok() | ||||||
} | ||||||
} | ||||||
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||||||
|
@@ -47,6 +55,7 @@ impl TryFrom<CellHeartbeatReqV1> for CellHeartbeat { | |||||
operation_mode: v.operation_mode, | ||||||
cbsd_category: v.cbsd_category, | ||||||
cbsd_id: v.cbsd_id, | ||||||
coverage_object: v.coverage_object, | ||||||
}) | ||||||
} | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
pub mod cli; | ||
pub mod coverage; | ||
pub mod entropy_report; | ||
mod error; | ||
mod file_info; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
CREATE TYPE signal_level AS ENUM ( | ||
'none', | ||
'low', | ||
'medium', | ||
'high' | ||
); | ||
|
||
CREATE TABLE hex_coverage ( | ||
uuid UUID NOT NULL, | ||
hex BIGINT NOT NULL, | ||
indoor BOOLEAN NOT NULL, | ||
cbsd_id TEXT NOT NULL, | ||
signal_level signal_level NOT NULL, | ||
coverage_claim_time TIMESTAMPTZ NOT NULL, | ||
inserted_at TIMESTAMPTZ NOT NULL, | ||
PRIMARY KEY (uuid, hex) | ||
); | ||
|
||
CREATE TABLE seniority ( | ||
cbsd_id TEXT NOT NULL, | ||
seniority_ts TIMESTAMPTZ NOT NULL, | ||
last_heartbeat TIMESTAMPTZ NOT NULL, | ||
uuid UUID NOT NULL, | ||
update_reason INT NOT NULL, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is update_reason an int and not an enum? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because then we can have it be the same type as the proto enum |
||
PRIMARY KEY (cbsd_id, seniority_ts) | ||
); | ||
|
||
ALTER TABLE heartbeats ADD COLUMN coverage_object UUID; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe not a concern depending on the expected volume of coverage objects, but
ulid-rs
may be good to keep in mind for "lexicographically sortable" IDs that are UUIDv4 compatible to prevent too much fragmentation in the databaseThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would absolutely prefer ulids, but we are given the uuids. we don't decide them