add boolean type
This commit is contained in:
@@ -170,6 +170,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
let cos_tlm_handle = tlm
|
||||
.register("simple_producer/cos".into(), TelemetryDataType::Float64)
|
||||
.await?;
|
||||
let bool_tlm_handle = tlm
|
||||
.register("simple_producer/bool".into(), TelemetryDataType::Boolean)
|
||||
.await?;
|
||||
|
||||
let sin2_tlm_handle = tlm
|
||||
.register("simple_producer/sin2".into(), TelemetryDataType::Float32)
|
||||
@@ -239,6 +242,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||
Value::Float64((f64::TAU() * (index as f64) / (1000.0_f64)).cos()),
|
||||
publish_time,
|
||||
));
|
||||
tasks.push(bool_tlm_handle.publish(Value::Boolean(index % 1000 > 500), publish_time));
|
||||
tasks.push(sin2_tlm_handle.publish(
|
||||
Value::Float32((f32::TAU() * (index as f32) / (500.0_f32)).sin()),
|
||||
publish_time,
|
||||
|
||||
29
frontend/src/components/BooleanText.vue
Normal file
29
frontend/src/components/BooleanText.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, watch } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
value: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update', value: string): void;
|
||||
}>();
|
||||
|
||||
const display_value = computed(() => {
|
||||
return props.value ? 'true' : 'false';
|
||||
});
|
||||
watch(
|
||||
[display_value],
|
||||
([display_str]) => {
|
||||
emit('update', display_str);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
{{ display_value }}
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -6,6 +6,7 @@ const props = defineProps<{
|
||||
value: number;
|
||||
max_width: number;
|
||||
copyable?: boolean;
|
||||
include_span?: boolean;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
(e: 'update', value: string): void;
|
||||
@@ -14,6 +15,9 @@ const emit = defineEmits<{
|
||||
const copyable = computed(() => {
|
||||
return props.copyable || false;
|
||||
});
|
||||
const include_span = computed(() => {
|
||||
return props.include_span || false;
|
||||
});
|
||||
|
||||
const display_value = computed(() => {
|
||||
if (props.value == 0) {
|
||||
@@ -61,9 +65,15 @@ const display_value = computed(() => {
|
||||
}
|
||||
return precision;
|
||||
});
|
||||
watch([display_value], ([display_str]) => {
|
||||
watch(
|
||||
[display_value],
|
||||
([display_str]) => {
|
||||
emit('update', display_str);
|
||||
});
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -73,11 +83,14 @@ watch([display_value], ([display_str]) => {
|
||||
v-bind="$attrs"
|
||||
></CopyableDynamicSpan>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-else-if="include_span">
|
||||
<span v-bind="$attrs">
|
||||
{{ display_value }}
|
||||
</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ display_value }}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
|
||||
@@ -96,12 +96,21 @@ watch([value], ([val]) => {
|
||||
if (val) {
|
||||
const val_t = Date.parse(val.timestamp);
|
||||
if (val_t >= min_x) {
|
||||
const item_val = val.value[
|
||||
telemetry_data.value!.data_type
|
||||
] as number;
|
||||
const raw_item_val = val.value[telemetry_data.value!.data_type];
|
||||
let item_val = 0;
|
||||
if (
|
||||
['Float32', 'Float64'].some(
|
||||
(e) => e == telemetry_data.value!.data_type,
|
||||
)
|
||||
) {
|
||||
item_val = raw_item_val as number;
|
||||
} else if (telemetry_data.value!.data_type == 'Boolean') {
|
||||
item_val = (raw_item_val as boolean) ? 1 : 0;
|
||||
}
|
||||
const new_item = {
|
||||
x: val_t,
|
||||
y: item_val,
|
||||
value: raw_item_val,
|
||||
} as Point;
|
||||
memo.value.insert(new_item, data_min_sep.value);
|
||||
if (item_val < min.value) {
|
||||
@@ -131,10 +140,21 @@ watch(
|
||||
const response = (await res.json()) as TelemetryDataItem[];
|
||||
for (const data_item of response) {
|
||||
const val_t = Date.parse(data_item.timestamp);
|
||||
const item_val = data_item.value[type] as number;
|
||||
const raw_item_val = data_item.value[type];
|
||||
let item_val = 0;
|
||||
if (
|
||||
['Float32', 'Float64'].some(
|
||||
(e) => e == telemetry_data.value!.data_type,
|
||||
)
|
||||
) {
|
||||
item_val = raw_item_val as number;
|
||||
} else if (type == 'Boolean') {
|
||||
item_val = (raw_item_val as boolean) ? 1 : 0;
|
||||
}
|
||||
const new_item = {
|
||||
x: val_t,
|
||||
y: item_val,
|
||||
value: raw_item_val,
|
||||
} as Point;
|
||||
memo.value.insert(new_item);
|
||||
if (item_val < min.value) {
|
||||
@@ -392,7 +412,7 @@ function onMouseExit(event: MouseEvent) {
|
||||
class="fade_other_selected label"
|
||||
:x="graph_data.x_map(toValue(graph_data.max_x)) + text_offset"
|
||||
:y="axis_data.y_map(current_data_point.y)"
|
||||
:value="current_data_point.y"
|
||||
:value="current_data_point.value"
|
||||
>
|
||||
</ValueLabel>
|
||||
<template v-if="toValue(graph_data.legend_enabled)">
|
||||
@@ -445,9 +465,10 @@ function onMouseExit(event: MouseEvent) {
|
||||
<span>{{ telemetry_data?.data_type }}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<span>{{
|
||||
current_data_point?.y || 'Missing Data'
|
||||
<span v-if="current_data_point !== undefined">{{
|
||||
current_data_point.value
|
||||
}}</span>
|
||||
<span v-else>Missing Data</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
|
||||
@@ -55,6 +55,7 @@ const numeric_data = computed(() => {
|
||||
v-bind="$attrs"
|
||||
:value="numeric_data"
|
||||
:max_width="10"
|
||||
include_span
|
||||
></NumericText>
|
||||
<span v-else v-bind="$attrs">
|
||||
Cannot Display Data of Type {{ telemetry_data!.data_type }}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, useTemplateRef, watch } from 'vue';
|
||||
import NumericText from '@/components/NumericText.vue';
|
||||
import BooleanText from '@/components/BooleanText.vue';
|
||||
|
||||
defineProps<{
|
||||
x: number;
|
||||
y: number;
|
||||
value: number;
|
||||
class?: string;
|
||||
value: number | boolean;
|
||||
}>();
|
||||
|
||||
const background_offset = computed(() => 5);
|
||||
@@ -34,7 +34,7 @@ function update_value_text(text: string) {
|
||||
|
||||
<template>
|
||||
<rect
|
||||
:class="$props.class"
|
||||
:class="$attrs.class"
|
||||
:x="x - background_offset"
|
||||
:y="y - y_offset - background_offset"
|
||||
:width="label_width + background_offset * 2"
|
||||
@@ -42,10 +42,16 @@ function update_value_text(text: string) {
|
||||
></rect>
|
||||
<text :class="$props.class" ref="label-ref" :x="x" :y="y">
|
||||
<NumericText
|
||||
v-if="typeof value == 'number'"
|
||||
:value="value"
|
||||
:max_width="6"
|
||||
@update="update_value_text"
|
||||
></NumericText>
|
||||
<BooleanText
|
||||
v-else-if="typeof value == 'boolean'"
|
||||
:value="value"
|
||||
@update="update_value_text"
|
||||
></BooleanText>
|
||||
</text>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
value: number | boolean;
|
||||
}
|
||||
|
||||
export class PointLine {
|
||||
|
||||
@@ -5,12 +5,14 @@ package core;
|
||||
enum TelemetryDataType {
|
||||
Float32 = 0;
|
||||
Float64 = 1;
|
||||
Boolean = 2;
|
||||
}
|
||||
|
||||
message TelemetryValue {
|
||||
oneof value {
|
||||
float float_32 = 1;
|
||||
double float_64 = 2;
|
||||
bool boolean = 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ impl CoreTelemetryService {
|
||||
let expected_type = match value {
|
||||
Value::Float32(_) => TelemetryDataType::Float32,
|
||||
Value::Float64(_) => TelemetryDataType::Float64,
|
||||
Value::Boolean(_) => TelemetryDataType::Boolean,
|
||||
};
|
||||
if expected_type != tlm_data.data.definition.data_type {
|
||||
return Err(Status::failed_precondition("Data Type Mismatch"));
|
||||
@@ -124,6 +125,7 @@ impl CoreTelemetryService {
|
||||
let value = match value {
|
||||
Value::Float32(x) => TelemetryDataValue::Float32(x),
|
||||
Value::Float64(x) => TelemetryDataValue::Float64(x),
|
||||
Value::Boolean(x) => TelemetryDataValue::Boolean(x),
|
||||
};
|
||||
let _ = tlm_data.data.data.send_replace(Some(TelemetryDataItem {
|
||||
value: value.clone(),
|
||||
|
||||
@@ -30,3 +30,16 @@ primitive_write_read!(i8, 1);
|
||||
|
||||
primitive_write_read!(f64, 8);
|
||||
primitive_write_read!(f32, 4);
|
||||
|
||||
impl FileWriteableType for bool {
|
||||
fn write_to_file(self, file: &mut impl Write) -> std::io::Result<()> {
|
||||
file.write_all(&[if self { 0x01 } else { 0x00 }])
|
||||
}
|
||||
}
|
||||
impl FileReadableType for bool {
|
||||
fn read_from_file(file: &mut impl Read) -> std::io::Result<Self> {
|
||||
let mut buffer = [0u8; 1];
|
||||
file.read_exact(&mut buffer)?;
|
||||
Ok(buffer[0] != 0x00)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ use serde::{Deserialize, Serialize};
|
||||
pub enum TelemetryDataValue {
|
||||
Float32(f32),
|
||||
Float64(f64),
|
||||
Boolean(bool),
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ impl HistorySegmentFile {
|
||||
match value {
|
||||
TelemetryDataValue::Float32(value) => file.write_data::<f32>(*value)?,
|
||||
TelemetryDataValue::Float64(value) => file.write_data::<f64>(*value)?,
|
||||
TelemetryDataValue::Boolean(value) => file.write_data::<bool>(*value)?,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +347,10 @@ impl HistorySegmentFile {
|
||||
self.file_position += 8;
|
||||
Ok(TelemetryDataValue::Float64(self.file.read_data::<f64>()?))
|
||||
}
|
||||
TelemetryDataType::Boolean => {
|
||||
self.file_position += 1;
|
||||
Ok(TelemetryDataValue::Boolean(self.file.read_data::<bool>()?))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +362,7 @@ impl HistorySegmentFile {
|
||||
let item_length = match telemetry_data_type {
|
||||
TelemetryDataType::Float32 => 4,
|
||||
TelemetryDataType::Float64 => 8,
|
||||
TelemetryDataType::Boolean => 1,
|
||||
};
|
||||
let desired_position =
|
||||
Self::HEADER_LENGTH + self.length * Self::TIMESTAMP_LENGTH + index * item_length;
|
||||
|
||||
Reference in New Issue
Block a user