109 lines
3.6 KiB
TypeScript
109 lines
3.6 KiB
TypeScript
import { box } from "boxed_value";
|
|
import { WDENVKey, Translation, FormatTranslationMap } from "./interfaces";
|
|
import { snakeCase, get, isUndefined } from "lodash";
|
|
|
|
/** I would rather not deal with all the weird edge cases that come with
|
|
* supporting strings and numbers right now. It adds too many edge cases for the
|
|
* FE to validate against. Example: Needing to conditionally determine if an ENV
|
|
* key is string vs. number vs. bool. Using only numbers (and translating values
|
|
* when transmitting) allows us to minimize the use of such conditionals.
|
|
* When we need to support text that users will read, I can re-visit this. */
|
|
export enum SPECIAL_VALUES {
|
|
FALSE = 0,
|
|
TRUE = 1,
|
|
TOP_LEFT = 2,
|
|
TOP_RIGHT = 3,
|
|
BOTTOM_LEFT = 4,
|
|
BOTTOM_RIGHT = 5,
|
|
X = 6,
|
|
Y = 7
|
|
}
|
|
|
|
/** Sometimes, ENV var values are not available but rendering must still be
|
|
* performed. This map provides a set of defaults for every ENV var. */
|
|
export const WD_KEY_DEFAULTS = {
|
|
CAMERA_CALIBRATION_calibration_along_axis: SPECIAL_VALUES.X,
|
|
CAMERA_CALIBRATION_image_bot_origin_location: SPECIAL_VALUES.BOTTOM_LEFT,
|
|
CAMERA_CALIBRATION_invert_hue_selection: SPECIAL_VALUES.TRUE,
|
|
CAMERA_CALIBRATION_blur: 5,
|
|
CAMERA_CALIBRATION_calibration_object_separation: 100,
|
|
CAMERA_CALIBRATION_camera_offset_x: 50,
|
|
CAMERA_CALIBRATION_camera_offset_y: 100,
|
|
CAMERA_CALIBRATION_coord_scale: 0,
|
|
CAMERA_CALIBRATION_H_HI: 160,
|
|
CAMERA_CALIBRATION_H_LO: 20,
|
|
CAMERA_CALIBRATION_iteration: 1,
|
|
CAMERA_CALIBRATION_morph: 5,
|
|
CAMERA_CALIBRATION_S_HI: 255,
|
|
CAMERA_CALIBRATION_S_LO: 100,
|
|
CAMERA_CALIBRATION_total_rotation_angle: 0,
|
|
CAMERA_CALIBRATION_V_HI: 255,
|
|
CAMERA_CALIBRATION_V_LO: 100,
|
|
WEED_DETECTOR_blur: 15,
|
|
WEED_DETECTOR_H_HI: 90,
|
|
WEED_DETECTOR_H_LO: 30,
|
|
WEED_DETECTOR_iteration: 4,
|
|
WEED_DETECTOR_morph: 6,
|
|
WEED_DETECTOR_S_HI: 255,
|
|
WEED_DETECTOR_S_LO: 50,
|
|
WEED_DETECTOR_V_HI: 255,
|
|
WEED_DETECTOR_V_LO: 50,
|
|
};
|
|
|
|
/** The runtime equivalent for WeedDetectorENVKey.
|
|
* Good for iterating and whatnot. */
|
|
export const EVERY_WD_KEY: WDENVKey[] =
|
|
Object.keys(WD_KEY_DEFAULTS).map((x: WDENVKey) => x);
|
|
|
|
export const DEFAULT_FORMATTER: Translation = {
|
|
format: (key, val): number | string => {
|
|
switch (key) {
|
|
case "CAMERA_CALIBRATION_calibration_along_axis":
|
|
case "CAMERA_CALIBRATION_image_bot_origin_location":
|
|
case "CAMERA_CALIBRATION_invert_hue_selection":
|
|
return ("" + (SPECIAL_VALUES[val] || val));
|
|
default:
|
|
return val;
|
|
}
|
|
},
|
|
parse: (__, val) => {
|
|
try {
|
|
const b = box(JSON.parse(val));
|
|
switch (b.kind) {
|
|
case "number":
|
|
return b.value;
|
|
case "boolean":
|
|
case "string":
|
|
return getSpecialValue(val);
|
|
default:
|
|
throw new Error("BAD DATA TYPE");
|
|
}
|
|
|
|
} catch (error) {
|
|
throw new Error(`An input from FarmWare caused a crash.
|
|
This is the value we got: ${val}
|
|
This is the error: ${error}
|
|
`);
|
|
}
|
|
}
|
|
};
|
|
/** If we hit any "special cases", we can register them here. */
|
|
export const TRANSLATORS: FormatTranslationMap = {};
|
|
/** We only expect certain string values from the weed detector.
|
|
* Tokens like "BOTTOM_RIGHT" or "X" all have a numeric counterpart.
|
|
* This function converts such strings to their numeric equivalent.
|
|
* If a matching numeric code is not found, throws an exception.
|
|
*/
|
|
export function getSpecialValue(key: string | number):
|
|
SPECIAL_VALUES {
|
|
|
|
const k = snakeCase(("" + key).toUpperCase()).toUpperCase();
|
|
const v = get(SPECIAL_VALUES, k, NaN);
|
|
|
|
if (isUndefined(v) || isNaN(v)) {
|
|
throw new Error("Not a SPECIAL_VALUE: " + k);
|
|
} else {
|
|
return v;
|
|
}
|
|
}
|