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