Skip to content

Commit

Permalink
Merge pull request #508 from gabrielburnworth/master
Browse files Browse the repository at this point in the history
Experimental/Future features
  • Loading branch information
RickCarlino committed Oct 20, 2017
2 parents 8fd4547 + 5212cfb commit 0c43348
Show file tree
Hide file tree
Showing 18 changed files with 301 additions and 75 deletions.
16 changes: 15 additions & 1 deletion webpack/__tests__/test_util.ts
Expand Up @@ -9,7 +9,8 @@ import {
SemverResult,
trim,
bitArray,
withTimeout
withTimeout,
minFwVersionCheck
} from "../util";
describe("util", () => {
describe("safeStringFetch", () => {
Expand Down Expand Up @@ -174,3 +175,16 @@ describe("withTimeout()", () => {
}, fail);
});
});

describe("minFwVersionCheck()", () => {
it("firmware version meets or exceeds minimum", () => {
expect(minFwVersionCheck("1.0.1R", "1.0.1")).toBeTruthy();
expect(minFwVersionCheck("1.0.2F", "1.0.1")).toBeTruthy();
});

it("firmware version doesn't meet minimum", () => {
expect(minFwVersionCheck("1.0.0R", "1.0.1")).toBeFalsy();
expect(minFwVersionCheck(undefined, "1.0.1")).toBeFalsy();
expect(minFwVersionCheck("1.0.0", "1.0.1")).toBeFalsy();
});
});
3 changes: 2 additions & 1 deletion webpack/constants.ts
Expand Up @@ -318,7 +318,8 @@ export namespace Content {
export const MQTT_DISCONNECTED =
`Your web browser is unable to connect to the message broker.
You might be behind a firewall or disconnected from the Internet. Check
your network settings.`.replace(/\s+/g, " ");
your network settings.
View Device > Connectivity for more details.`.replace(/\s+/g, " ");

export const MALFORMED_MESSAGE_REC_UPGRADE =
`FarmBot sent a malformed message. You may need to upgrade
Expand Down
39 changes: 37 additions & 2 deletions webpack/devices/components/__tests__/motors_test.tsx
@@ -1,8 +1,8 @@
import * as React from "react";
import { MotorsProps } from "../interfaces";
import { bot } from "../../../__test_support__/fake_state/bot";
import { Motors } from "../hardware_settings/motors";
import { render } from "enzyme";
import { Motors, StepsPerMmSettings } from "../hardware_settings/motors";
import { render, shallow } from "enzyme";

describe("<Motors/>", () => {
it("renders the base case", () => {
Expand All @@ -16,4 +16,39 @@ describe("<Motors/>", () => {
"Max Speed (steps/s)"
].map(xpectd => expect(txt).toContain(xpectd));
});

it("doesn't render homing speed", () => {
const props: MotorsProps = { dispatch: jest.fn(), bot };
props.bot.hardware.informational_settings.firmware_version = "4.0.0R";
const wrapper = render(<Motors {...props} />);
expect(wrapper.text()).not.toContain("Homing Speed");
});

it("renders homing speed", () => {
const props: MotorsProps = { dispatch: jest.fn(), bot };
props.bot.hardware.informational_settings.firmware_version = "5.1.0R";
const wrapper = render(<Motors {...props} />);
expect(wrapper.text()).toContain("Homing Speed");
});
});

describe("<StepsPerMmSettings/>", () => {
it("renders OS settings", () => {
const props: MotorsProps = { dispatch: jest.fn(), bot };
props.bot.hardware.informational_settings.firmware_version = "4.0.0R";
const wrapper = shallow(<StepsPerMmSettings {...props} />);
const firstInputProps = wrapper.find("BotConfigInputBox")
// tslint:disable-next-line:no-any
.first().props() as any;
expect(firstInputProps.setting).toBe("steps_per_mm_x");
});

it("renders mcu settings", () => {
const props: MotorsProps = { dispatch: jest.fn(), bot };
props.bot.hardware.informational_settings.firmware_version = "5.0.5R";
const wrapper = shallow(<StepsPerMmSettings {...props} />);
const firstInputProps = wrapper.find("NumericMCUInputGroup")
.first().props();
expect(firstInputProps.x).toBe("movement_step_per_mm_x");
});
});
91 changes: 55 additions & 36 deletions webpack/devices/components/hardware_settings/motors.tsx
Expand Up @@ -12,11 +12,54 @@ import { Row, Col } from "../../../ui/index";
import { Header } from "./header";
import { Collapse } from "@blueprintjs/core";
import { McuInputBox } from "../mcu_input_box";
import { minFwVersionCheck } from "../../../util";

export function StepsPerMmSettings({ dispatch, bot }: MotorsProps) {
const { firmware_version } = bot.hardware.informational_settings;
if (minFwVersionCheck(firmware_version, "5.0.5")) {
return <NumericMCUInputGroup
name={t("Steps per MM")}
tooltip={t(ToolTips.STEPS_PER_MM)}
x={"movement_step_per_mm_x"}
y={"movement_step_per_mm_y"}
z={"movement_step_per_mm_z"}
bot={bot}
dispatch={dispatch} />;
} else {
return <Row>
<Col xs={6}>
<label>
{t("Steps per MM")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.STEPS_PER_MM)} />
</Col>
<Col xs={2}>
<BotConfigInputBox
setting="steps_per_mm_x"
bot={bot}
dispatch={dispatch} />
</Col>
<Col xs={2}>
<BotConfigInputBox
setting="steps_per_mm_y"
bot={bot}
dispatch={dispatch} />
</Col>
<Col xs={2}>
<BotConfigInputBox
setting="steps_per_mm_z"
bot={bot}
dispatch={dispatch} />
</Col>
</Row>;
}
}

export function Motors({ dispatch, bot }: MotorsProps) {

const { mcu_params } = bot.hardware;
const { motors } = bot.controlPanelState;
const { firmware_version } = bot.hardware.informational_settings;

return <section>
<Header
Expand Down Expand Up @@ -61,16 +104,15 @@ export function Motors({ dispatch, bot }: MotorsProps) {
z={"movement_max_spd_z"}
bot={bot}
dispatch={dispatch} />
{/*
This works. Uncomment when it is time to relase. -RC.
<NumericMCUInputGroup
name={t("Homing Speed (steps/s)")}
tooltip={t(ToolTips.HOME_SPEED)}
x={"movement_home_spd_x"}
y={"movement_home_spd_y"}
z={"movement_home_spd_z"}
bot={bot}
dispatch={dispatch} /> */}
{minFwVersionCheck(firmware_version, "5.0.5") &&
<NumericMCUInputGroup
name={t("Homing Speed (steps/s)")}
tooltip={t(ToolTips.HOME_SPEED)}
x={"movement_home_spd_x"}
y={"movement_home_spd_y"}
z={"movement_home_spd_z"}
bot={bot}
dispatch={dispatch} />}
<NumericMCUInputGroup
name={t("Minimum Speed (steps/s)")}
tooltip={t(ToolTips.MIN_SPEED)}
Expand All @@ -87,32 +129,9 @@ export function Motors({ dispatch, bot }: MotorsProps) {
z={"movement_steps_acc_dec_z"}
bot={bot}
dispatch={dispatch} />
<Row>
<Col xs={6}>
<label>
{t("Steps per MM")}
</label>
<SpacePanelToolTip tooltip={t(ToolTips.STEPS_PER_MM)} />
</Col>
<Col xs={2}>
<BotConfigInputBox
setting="steps_per_mm_x"
bot={bot}
dispatch={dispatch} />
</Col>
<Col xs={2}>
<BotConfigInputBox
setting="steps_per_mm_y"
bot={bot}
dispatch={dispatch} />
</Col>
<Col xs={2}>
<BotConfigInputBox
setting="steps_per_mm_z"
bot={bot}
dispatch={dispatch} />
</Col>
</Row>
<StepsPerMmSettings
dispatch={dispatch}
bot={bot} />
<BooleanMCUInputGroup
name={t("Always Power Motors")}
tooltip={t(ToolTips.ALWAYS_POWER_MOTORS)}
Expand Down
2 changes: 1 addition & 1 deletion webpack/devices/interfaces.ts
Expand Up @@ -84,7 +84,7 @@ export type Xyz = "x" | "y" | "z";
export type Axis = Xyz | "all";

export type BotPosition = Record<Xyz, (number | undefined)>;
export type BotLocationData = Record<LocationName, BotPosition> | undefined;
export type BotLocationData = Record<LocationName, BotPosition>;

export type StepsPerMmXY = Record<"x" | "y", (number | undefined)>;

Expand Down
6 changes: 5 additions & 1 deletion webpack/farm_designer/__tests__/farm_designer_test.tsx
Expand Up @@ -25,7 +25,11 @@ describe("<FarmDesigner/>", () => {
plants: [],
toolSlots: [],
crops: [],
botPosition: { x: undefined, y: undefined, z: undefined },
botLocationData: {
position: { x: undefined, y: undefined, z: undefined },
scaled_encoders: { x: undefined, y: undefined, z: undefined },
raw_encoders: { x: undefined, y: undefined, z: undefined },
},
botMcuParams: bot.hardware.mcu_params,
stepsPerMmXY: { x: undefined, y: undefined }
};
Expand Down
2 changes: 1 addition & 1 deletion webpack/farm_designer/index.tsx
Expand Up @@ -170,7 +170,7 @@ export class FarmDesigner extends React.Component<Props, Partial<State>> {
plants={this.props.plants}
points={this.props.points}
toolSlots={this.props.toolSlots}
botPosition={this.props.botPosition}
botLocationData={this.props.botLocationData}
botSize={botSize}
stopAtHome={stopAtHome}
hoveredPlant={this.props.hoveredPlant}
Expand Down
6 changes: 3 additions & 3 deletions webpack/farm_designer/interfaces.ts
Expand Up @@ -11,7 +11,7 @@ import {
} from "../resources/tagged_resources";
import { PlantPointer } from "../interfaces";
import { SlotWithTool } from "../resources/interfaces";
import { BotPosition, StepsPerMmXY } from "../devices/interfaces";
import { BotPosition, StepsPerMmXY, BotLocationData } from "../devices/interfaces";
import { isNumber } from "lodash";
import { McuParams } from "farmbot/dist";
import { AxisNumberProperty, BotSize } from "./map/interfaces";
Expand Down Expand Up @@ -46,7 +46,7 @@ export interface Props {
plants: TaggedPlantPointer[];
toolSlots: SlotWithTool[];
crops: TaggedCrop[];
botPosition: BotPosition;
botLocationData: BotLocationData;
botMcuParams: McuParams;
stepsPerMmXY: StepsPerMmXY;
}
Expand Down Expand Up @@ -165,7 +165,7 @@ export interface GardenMapProps {
selectedPlant: TaggedPlantPointer | undefined;
hoveredPlant: TaggedPlantPointer | undefined;
crops: TaggedCrop[];
botPosition: BotPosition;
botLocationData: BotLocationData;
botSize: BotSize;
stopAtHome: Record<"x" | "y", boolean>;
zoomLvl: number;
Expand Down
6 changes: 5 additions & 1 deletion webpack/farm_designer/map/__tests__/garden_map_test.tsx
Expand Up @@ -38,7 +38,11 @@ describe("<GardenPlant/>", () => {
plants: [],
points: [],
toolSlots: [],
botPosition: { x: 0, y: 0, z: 0 },
botLocationData: {
position: { x: 0, y: 0, z: 0 },
scaled_encoders: { x: undefined, y: undefined, z: undefined },
raw_encoders: { x: undefined, y: undefined, z: undefined },
},
botSize: {
x: { value: 3000, isDefault: true },
y: { value: 1500, isDefault: true }
Expand Down
70 changes: 67 additions & 3 deletions webpack/farm_designer/map/__tests__/virtual_farmbot_test.tsx
@@ -1,13 +1,31 @@
const mockStorj: Dictionary<boolean> = {};

jest.mock("../../../session", () => {
return {
Session: {
getBool: (k: string) => {
mockStorj[k] = !!mockStorj[k];
return mockStorj[k];
},
}
};
});

import * as React from "react";
import { VirtualFarmBot } from "../virtual_farmbot";
import { shallow } from "enzyme";
import { VirtualFarmBotProps } from "../interfaces";
import { BotOriginQuadrant } from "../../interfaces";
import { Dictionary } from "farmbot";

describe("<VirtualFarmBot/>", () => {
function fakeProps(): VirtualFarmBotProps {
return {
botPosition: { x: 0, y: 0, z: 0 },
botLocationData: {
position: { x: 0, y: 0, z: 0 },
scaled_encoders: { x: undefined, y: undefined, z: undefined },
raw_encoders: { x: undefined, y: undefined, z: undefined },
},
mapTransformProps: {
quadrant: 1, gridSize: { x: 3000, y: 1500 }
},
Expand Down Expand Up @@ -56,11 +74,57 @@ describe("<VirtualFarmBot/>", () => {
it("changes location", () => {
const p = fakeProps();
p.mapTransformProps.quadrant = 2;
p.botPosition = { x: 100, y: 200, z: 0 };
p.botLocationData.position = { x: 100, y: 200, z: 0 };
const result = shallow(<VirtualFarmBot {...p } />);
expect(result.find("#gantry").props().x).toEqual(90);
const gantry = result.find("#gantry");
expect(gantry.length).toEqual(1);
expect(gantry.props().x).toEqual(90);
const UTM = result.find("circle").props();
expect(UTM.cx).toEqual(100);
expect(UTM.cy).toEqual(200);
});

it("shows trail", () => {
mockStorj["displayTrail"] = true;
sessionStorage["virtualTrail"] = JSON.stringify([
{ x: 1, y: 1 }, { x: 2, y: 2 }, { x: 3, y: 3 }, { x: 4, y: 4 }]);
const p = fakeProps();
p.mapTransformProps.quadrant = 2;
const wrapper = shallow(<VirtualFarmBot {...p } />);
const lines = wrapper.find("#trail").find("line");
expect(lines.length).toEqual(4);
expect(lines.first().props()).toEqual({
id: "trail-line-1",
stroke: "red",
strokeOpacity: 0.25,
strokeWidth: 0.5,
x1: 2, x2: 1, y1: 2, y2: 1
});
expect(lines.last().props()).toEqual({
id: "trail-line-4",
stroke: "red",
strokeOpacity: 1,
strokeWidth: 2,
x1: 0, x2: 4, y1: 0, y2: 4
});
});

it("shows encoder position", () => {
mockStorj["encoderFigure"] = true;
const p = fakeProps();
p.mapTransformProps.quadrant = 2;
p.botLocationData.position = { x: 100, y: 200, z: 0 };
p.botLocationData.scaled_encoders = { x: 300, y: 400, z: 0 };
const wrapper = shallow(<VirtualFarmBot {...p } />);
expect(wrapper.find("#gantry").first().props().x).toEqual(90);
expect(wrapper.find("#gantry").last().props().x).toEqual(290);
const motorsUTM = wrapper.find("circle").first().props();
expect(motorsUTM.cx).toEqual(100);
expect(motorsUTM.cy).toEqual(200);
expect(motorsUTM.fillOpacity).toEqual(0.75);
const encodersUTM = wrapper.find("circle").last().props();
expect(encodersUTM.cx).toEqual(300);
expect(encodersUTM.cy).toEqual(400);
expect(encodersUTM.fillOpacity).toEqual(0.25);
});
});
6 changes: 3 additions & 3 deletions webpack/farm_designer/map/garden_map.tsx
Expand Up @@ -282,7 +282,7 @@ export class GardenMap extends
<FarmBotLayer
mapTransformProps={mapTransformProps}
visible={!!this.props.showFarmbot}
botPosition={this.props.botPosition}
botLocationData={this.props.botLocationData}
stopAtHome={this.props.stopAtHome}
botSize={this.props.botSize}
plantAreaOffset={this.props.gridOffset} />
Expand All @@ -304,8 +304,8 @@ export class GardenMap extends
plantAreaOffset={this.props.gridOffset} />
{this.state.selectionBox &&
<SelectionBox
selectionBox={this.state.selectionBox}
mapTransformProps={mapTransformProps} />}
selectionBox={this.state.selectionBox}
mapTransformProps={mapTransformProps} />}
</svg>
</svg>
</div>;
Expand Down

0 comments on commit 0c43348

Please sign in to comment.