Combine the various property controls into one component
propertyControl now handles several different property types, based on the thing description. This reduces duplication and should keep the code cleaner. In the future this will become a part of a labthings-vue package, I hope!
This commit is contained in:
parent
595101248e
commit
488493385f
3 changed files with 100 additions and 32 deletions
|
|
@ -44,7 +44,7 @@
|
|||
<i class="material-icons">refresh</i>
|
||||
</a>
|
||||
</div>
|
||||
<div v-else class="input-and-buttons-container">
|
||||
<div v-if="dataType == 'other'" class="input-and-buttons-container">
|
||||
<input
|
||||
:value="value"
|
||||
class="uk-form-small numeric-setting-line-input"
|
||||
|
|
@ -62,6 +62,10 @@ export default {
|
|||
name: "PropertyControl",
|
||||
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
propertyName: {
|
||||
type: String,
|
||||
required: true
|
||||
|
|
@ -79,7 +83,7 @@ export default {
|
|||
|
||||
data: () => {
|
||||
return {
|
||||
value: {},
|
||||
value: undefined,
|
||||
valueOnEnter: undefined,
|
||||
focused: false
|
||||
};
|
||||
|
|
@ -90,21 +94,35 @@ export default {
|
|||
return this.readBackDelay !== undefined;
|
||||
},
|
||||
propertyDescription: function() {
|
||||
return this.thingDescription.properties[this.propertyName];
|
||||
try {
|
||||
return this.thingDescription.properties[this.propertyName];
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
readPropertyUrl: function() {
|
||||
let href = this.formHref("readproperty");
|
||||
return this.prependTdBaseUri(href);
|
||||
},
|
||||
writePropertyUrl: function() {
|
||||
let href = this.formHref("writeproperty");
|
||||
return this.prependTdBaseUri(href);
|
||||
},
|
||||
dataType: function() {
|
||||
let prop = this.propertyDescription;
|
||||
if (prop == undefined) {
|
||||
return "undefined";
|
||||
}
|
||||
const num_types = ["integer", "float", "number"];
|
||||
if (num_types.includes(prop.type)) {
|
||||
return "number";
|
||||
}
|
||||
console.log("Prop type", prop.type, "is not in", num_types);
|
||||
if (prop.type == "array") {
|
||||
if (num_types.includes(prop.items)) {
|
||||
if (num_types.includes(prop.items.type)) {
|
||||
return "number_array";
|
||||
}
|
||||
if (Array.isArray(prop.items)) {
|
||||
if (prop.items.every(t => num_types.includes(t))) {
|
||||
if (prop.items.every(t => num_types.includes(t.type))) {
|
||||
return "number_array";
|
||||
}
|
||||
}
|
||||
|
|
@ -125,21 +143,60 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
readPropertyUrl: function() {
|
||||
// Ensure we read the property once the URL is known
|
||||
this.readProperty();
|
||||
}
|
||||
},
|
||||
|
||||
mounted: function() {
|
||||
this.readProperty();
|
||||
// Read the property when we're mounted - usually this won't
|
||||
// work because the URL isn't set yet. However, it's helpful if
|
||||
// the app is reloaded (e.g. from a dev server).
|
||||
if (this.value == undefined) {
|
||||
this.readProperty();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
formHref: function(op = "readproperty") {
|
||||
if (this.thingDescription == undefined) return undefined;
|
||||
try {
|
||||
let forms = this.propertyDescription.forms;
|
||||
let readForm = forms.find(f => f.op == op || f.op.includes(op));
|
||||
return readForm.href;
|
||||
} catch (error) {
|
||||
console.log(
|
||||
`Failed to find form for ${op} on ${this.propertyName}`,
|
||||
error
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
prependTdBaseUri: function(href) {
|
||||
if (href == undefined) return undefined;
|
||||
if (href.startsWith("http")) return href;
|
||||
if ("base" in this.thingDescription) {
|
||||
if (href.startsWith("/")) href = href.slice(1);
|
||||
if (!this.thingDescription.base.endsWith("/"))
|
||||
this.thingDescription.base += "/";
|
||||
return this.thingDescription.base + href;
|
||||
}
|
||||
return href;
|
||||
},
|
||||
readProperty: async function() {
|
||||
let response = await axios.get(this.propertyUrl);
|
||||
console.log(`Reading property ${this.propertyName}`);
|
||||
let response = await axios.get(this.readPropertyUrl);
|
||||
console.log(`Read property ${this.propertyName}`);
|
||||
this.value = response.data;
|
||||
console.log("Read property", this.propertyUrl, response.data);
|
||||
console.log("Read property", this.readPropertyUrl, response.data);
|
||||
return response.data;
|
||||
},
|
||||
writeProperty: async function() {
|
||||
try {
|
||||
let requestedValue = this.value;
|
||||
await axios.post(this.propertyUrl, requestedValue);
|
||||
await axios.post(this.writePropertyUrl, requestedValue);
|
||||
if (this.readBack) {
|
||||
await new Promise(r => setTimeout(r, this.readBackDelay));
|
||||
let newVal = await this.readProperty();
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export default {
|
|||
computed: {
|
||||
baseUri: function() {
|
||||
return `${this.$store.getters.baseUri}/`;
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
mounted: function() {
|
||||
|
|
@ -98,7 +98,7 @@ export default {
|
|||
|
||||
methods: {
|
||||
updateConfiguration: async function() {
|
||||
console.log("Showing the configuration is not yet fully implemented")
|
||||
console.log("Showing the configuration is not yet fully implemented");
|
||||
// Retrieve TDs for camera and stage
|
||||
let things = {};
|
||||
for (let thing of ["camera", "stage"]) {
|
||||
|
|
@ -106,17 +106,20 @@ export default {
|
|||
let response = await axios.get(this.baseUri + thing); // Get Thing Description
|
||||
things[thing] = response.data;
|
||||
} catch (error) {
|
||||
console.log(thing + " was missing", error)
|
||||
console.log(thing + " was missing", error);
|
||||
}
|
||||
}
|
||||
this.things = things; // We must set this.things in order to trigger the UI update
|
||||
this.things = things; // We must set this.things in order to trigger the UI update
|
||||
},
|
||||
updateActions: async function() {
|
||||
try {
|
||||
let response = await axios.get(this.baseUri + "system_control"); // Get Thing Description
|
||||
this.systemControlActions = response.data.actions;
|
||||
} catch (error) {
|
||||
console.log("system control was missing - shutdown/restart buttons will not appear", error)
|
||||
console.log(
|
||||
"system control was missing - shutdown/restart buttons will not appear",
|
||||
error
|
||||
);
|
||||
}
|
||||
},
|
||||
shutdownRequest: function() {
|
||||
|
|
@ -124,7 +127,7 @@ export default {
|
|||
() => {
|
||||
this.$store.commit("resetState");
|
||||
// Post and silence errors
|
||||
axios.post(this.baseUri + 'system_control/shutdown').catch(() => {});
|
||||
axios.post(this.baseUri + "system_control/shutdown").catch(() => {});
|
||||
},
|
||||
() => {}
|
||||
);
|
||||
|
|
@ -134,7 +137,7 @@ export default {
|
|||
() => {
|
||||
this.$store.commit("resetState");
|
||||
// Post and silence errors
|
||||
axios.post(this.baseUri + 'system_control/restart').catch(() => {});
|
||||
axios.post(this.baseUri + "system_control/restart").catch(() => {});
|
||||
},
|
||||
() => {}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,19 +12,22 @@
|
|||
<li class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Pi Camera Settings</a>
|
||||
<div class="uk-accordion-content">
|
||||
<NumericSettingLine
|
||||
<PropertyControl
|
||||
label="Exposure time"
|
||||
:property-url="cameraUri + 'exposure_time'"
|
||||
property-name="exposure_time"
|
||||
:thing-description="thingDescription"
|
||||
:read-back-delay="1000"
|
||||
/>
|
||||
<NumericSettingLine
|
||||
<PropertyControl
|
||||
label="Analogue gain"
|
||||
:property-url="cameraUri + 'analogue_gain'"
|
||||
property-name="analogue_gain"
|
||||
:thing-description="thingDescription"
|
||||
:read-back-delay="1000"
|
||||
/>
|
||||
<NumericArraySettingLine
|
||||
<PropertyControl
|
||||
label="Colour gains"
|
||||
:property-url="cameraUri + 'colour_gains'"
|
||||
property-name="colour_gains"
|
||||
:thing-description="thingDescription"
|
||||
:read-back-delay="1000"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -32,14 +35,16 @@
|
|||
<li class="uk-open">
|
||||
<a class="uk-accordion-title" href="#">Image Quality</a>
|
||||
<div class="uk-accordion-content">
|
||||
<NumericSettingLine
|
||||
<PropertyControl
|
||||
label="MJPEG stream bit rate"
|
||||
:property-url="cameraUri + 'mjpeg_bitrate'"
|
||||
property-name="mjpeg_bitrate"
|
||||
:thing-description="thingDescription"
|
||||
:read-back-delay="100"
|
||||
/>
|
||||
<NumericArraySettingLine
|
||||
<PropertyControl
|
||||
label="MJPEG stream resolution"
|
||||
:property-url="cameraUri + 'stream_resolution'"
|
||||
property-name="stream_resolution"
|
||||
:thing-description="thingDescription"
|
||||
:read-back-delay="100"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -92,8 +97,7 @@
|
|||
<script>
|
||||
import cameraCalibrationSettings from "./cameraSettingsComponents/cameraCalibrationSettings.vue";
|
||||
import miniStreamDisplay from "../../genericComponents/miniStreamDisplay.vue";
|
||||
import NumericSettingLine from "../../genericComponents/numericSettingLine.vue";
|
||||
import NumericArraySettingLine from "../../genericComponents/numericArraySettingLine.vue";
|
||||
import PropertyControl from "../../labThingsComponents/propertyControl.vue";
|
||||
|
||||
// Export main app
|
||||
export default {
|
||||
|
|
@ -102,8 +106,7 @@ export default {
|
|||
components: {
|
||||
cameraCalibrationSettings,
|
||||
miniStreamDisplay,
|
||||
NumericSettingLine,
|
||||
NumericArraySettingLine
|
||||
PropertyControl
|
||||
},
|
||||
|
||||
data: function() {
|
||||
|
|
@ -133,7 +136,8 @@ export default {
|
|||
{ text: "Normal (30fps)", value: 30 },
|
||||
{ text: "Low (15fps)", value: 15 },
|
||||
{ text: "Very low (10fps)", value: 10 }
|
||||
]
|
||||
],
|
||||
thingDescription: undefined
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -141,6 +145,10 @@ export default {
|
|||
cameraUri: function() {
|
||||
return `${this.$store.getters.baseUri}/camera/`;
|
||||
}
|
||||
},
|
||||
|
||||
mounted: async function() {
|
||||
this.thingDescription = await this.getThingDescription("camera");
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue