Skip to content

Commit

Permalink
favor write over read for analog pin status
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielburnworth committed Jul 7, 2021
1 parent 29c2908 commit c668321
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 34 deletions.
26 changes: 23 additions & 3 deletions frontend/controls/peripherals/__tests__/peripheral_list_test.tsx
Expand Up @@ -7,7 +7,7 @@ jest.mock("../../../device", () => ({ getDevice: () => mockDevice }));
import React from "react";
import { mount, shallow } from "enzyme";
import {
PeripheralList, AnalogSlider, AnalogSliderProps,
PeripheralList, AnalogSlider, AnalogSliderProps, calc8BitValue, PinIOMode,
} from "../peripheral_list";
import {
TaggedPeripheral,
Expand All @@ -16,6 +16,7 @@ import {
import { Pins } from "farmbot/dist";
import { PeripheralListProps } from "../interfaces";
import { Slider } from "@blueprintjs/core";
import { PinMode } from "../../../sequences/step_tiles/pin_support";

describe("<PeripheralList />", () => {
const fakeProps = (): PeripheralListProps => {
Expand Down Expand Up @@ -140,10 +141,29 @@ describe("<AnalogSlider />", () => {

it("renders read value", () => {
const p = fakeProps();
p.initialValue = 1000;
p.initialValue = 255;
const wrapper = shallow(<AnalogSlider {...p} />);
expect(wrapper.find(Slider).props().value).toEqual(249);
expect(wrapper.find(Slider).props().value).toEqual(255);
wrapper.find(Slider).simulate("change", 128);
expect(wrapper.find(Slider).props().value).toEqual(128);
});
});

describe("calc8BitValue()", () => {
it.each<[PinIOMode, number | undefined, PinMode, number]>([
[PinIOMode.input, 1000, PinMode.analog, 249],
[PinIOMode.input, 1, PinMode.digital, 255],
[PinIOMode.input, undefined, PinMode.analog, 0],
[PinIOMode.input, undefined, PinMode.digital, 0],
[PinIOMode.output, 128, PinMode.analog, 128],
[PinIOMode.output, 1, PinMode.digital, 255],
[PinIOMode.output, undefined, PinMode.digital, 0],
[PinIOMode.input_pullup, 1000, PinMode.analog, 6],
[PinIOMode.input_pullup, 1, PinMode.digital, 0],
[PinIOMode.input_pullup, undefined, PinMode.analog, 0],
[PinIOMode.input_pullup, undefined, PinMode.digital, 0],
])("returns correct value in i/o mode %s for %s in mode %s",
(ioMode, value, mode, expected) => {
expect(calc8BitValue(ioMode, value, mode)).toEqual(expected);
});
});
32 changes: 30 additions & 2 deletions frontend/controls/peripherals/peripheral_list.tsx
Expand Up @@ -8,6 +8,7 @@ import { Slider } from "@blueprintjs/core";
import { ANALOG } from "farmbot";
import { lockedClass } from "../locked_class";
import { round } from "lodash";
import { PinMode } from "../../sequences/step_tiles/pin_support/mode";

export const PeripheralList = (props: PeripheralListProps) =>
<div className="peripheral-list">
Expand Down Expand Up @@ -56,16 +57,43 @@ export class AnalogSlider
state: AnalogSliderState = { value: 0, controlled: false };
render() {
const { pin } = this.props;
const readValue = round((this.props.initialValue || 0) / 1024 * 255);
return <div className={"slider-container"}>
<Slider
disabled={!!this.props.disabled}
min={0}
max={255}
labelStepSize={255}
value={this.state.controlled ? this.state.value : readValue}
value={this.state.controlled ? this.state.value : this.props.initialValue}
onChange={value => this.setState({ value, controlled: true })}
onRelease={value => pin && writePin(pin, value, ANALOG)} />
</div>;
}
}

export enum PinIOMode {
"input" = 0,
"output" = 1,
"input_pullup" = 2,
}

/* Calculate 0-255 pin value based on pin i/o mode. */
export const calc8BitValue = (
pinIOMode: PinIOMode,
value: number | undefined,
mode: PinMode,
) => {
switch (pinIOMode) {
case PinIOMode.input:
return mode == PinMode.digital
? (value || 0) * 255
: round((value || 0) / 1024 * 255);
case PinIOMode.output:
return mode == PinMode.digital
? (value || 0) * 255
: value;
case PinIOMode.input_pullup:
return mode == PinMode.digital
? (1 - (value || 1)) * 255
: round((1024 - (value || 1024)) / 1024 * 255);
}
};
18 changes: 11 additions & 7 deletions frontend/messages/cards.tsx
Expand Up @@ -261,8 +261,11 @@ export const SEED_DATA_OPTIONS = (): DropDownItem[] => [
{ label: "Custom Bot", value: "none" },
];

export const SEED_DATA_OPTIONS_DDI: Record<string, DropDownItem> = {};
SEED_DATA_OPTIONS().map(ddi => SEED_DATA_OPTIONS_DDI[ddi.value] = ddi);
export const SEED_DATA_OPTIONS_DDI = (): Record<string, DropDownItem> => {
const options: Record<string, DropDownItem> = {};
SEED_DATA_OPTIONS().map(ddi => options[ddi.value] = ddi);
return options;
};

class SeedDataMissing
extends React.Component<SeedDataMissingProps, SeedDataMissingState> {
Expand Down Expand Up @@ -292,7 +295,7 @@ class SeedDataMissing
<FBSelect
key={this.state.selection}
list={SEED_DATA_OPTIONS()}
selectedItem={SEED_DATA_OPTIONS_DDI[this.state.selection]}
selectedItem={SEED_DATA_OPTIONS_DDI()[this.state.selection]}
onChange={seedAccount(this.dismiss)} />
</Col>
</Row>
Expand All @@ -303,14 +306,15 @@ class SeedDataMissing
export const ReSeedAccount = () => {
const [selection, setSelection] = React.useState("");
return <Row className={"re-seed"}>
<Col xs={6}>
<Col xs={7}>
<FBSelect
key={selection}
list={SEED_DATA_OPTIONS()}
selectedItem={SEED_DATA_OPTIONS_DDI[selection]}
list={SEED_DATA_OPTIONS().filter(x => x.value != "none")}
customNullLabel={t("Select a model")}
selectedItem={SEED_DATA_OPTIONS_DDI()[selection]}
onChange={ddi => setSelection("" + ddi.value)} />
</Col>
<Col xs={6}>
<Col xs={5}>
<button className={"fb-button green"}
onClick={() => selection && confirm(t(Content.RE_SEED_ACCOUNT)) &&
seedAccount()({ label: "", value: selection })}>
Expand Down
2 changes: 1 addition & 1 deletion frontend/sequences/step_tiles/pin_support/mode.tsx
Expand Up @@ -52,7 +52,7 @@ export function currentModeSelection(currentStep: ReadPin | WritePin) {
return { label: modes[pinMode], value: pinMode };
}

enum PinMode {
export enum PinMode {
digital = 0,
analog = 1,
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/settings/fbos_settings/fbos_details.tsx
Expand Up @@ -139,7 +139,7 @@ export interface MacAddressProps {
}

export const MacAddress = ({ wifi, nodeName, target }: MacAddressProps) =>
isString(nodeName) && !nodeName.includes("---")
isString(nodeName) && !nodeName.includes("---") && nodeName
? <p className={"mac-address"}>
<b>{t("MAC address")}: </b>{calcMac(nodeName, target, wifi)}
</p>
Expand Down
31 changes: 12 additions & 19 deletions frontend/settings/firmware/firmware_hardware_support.ts
Expand Up @@ -59,7 +59,7 @@ export const getBoardIdentifier =

export const isKnownBoard = (firmwareVersion: string | undefined): boolean => {
const boardIdentifier = getBoardIdentifier(firmwareVersion);
return ["R", "F", "G", "H", "E"].includes(boardIdentifier);
return Object.keys(FIRMWARE_LOOKUP).includes(boardIdentifier);
};

export const getBoardCategory =
Expand All @@ -84,26 +84,19 @@ export const boardType =
(firmwareVersion: string | undefined): FirmwareHardware | "unknown" => {
if (firmwareVersion === "none") { return "none"; }
const boardIdentifier = getBoardIdentifier(firmwareVersion);
switch (boardIdentifier) {
case "R":
return "arduino";
case "F":
return "farmduino";
case "G":
return "farmduino_k14";
case "H":
return "farmduino_k15";
case "I":
return "farmduino_k16";
case "E":
return "express_k10";
case "D":
return "express_k11";
default:
return "unknown";
}
return FIRMWARE_LOOKUP[boardIdentifier] || "unknown";
};

const FIRMWARE_LOOKUP: { [id: string]: FirmwareHardware } = {
R: "arduino",
F: "farmduino",
G: "farmduino_k14",
H: "farmduino_k15",
I: "farmduino_k16",
E: "express_k10",
D: "express_k11",
};

enum BoardLabels {
arduino = "Arduino/RAMPS (Genesis v1.2)",
farmduino = "Farmduino (Genesis v1.3)",
Expand Down
2 changes: 1 addition & 1 deletion frontend/wizard/checks.tsx
Expand Up @@ -301,7 +301,7 @@ export class FirmwareHardwareSelection
<FBSelect
key={selection}
list={SEED_DATA_OPTIONS()}
selectedItem={SEED_DATA_OPTIONS_DDI[selection]}
selectedItem={SEED_DATA_OPTIONS_DDI()[selection]}
onChange={this.onChange} />
{notSeeded &&
<div className={"seed-checkbox"}>
Expand Down

0 comments on commit c668321

Please sign in to comment.