Finally get rid of `devices.current`

pull/492/head
Rick Carlino 2017-10-10 12:59:08 -05:00
parent e1e54e8449
commit a14c5d3f71
34 changed files with 138 additions and 181 deletions

View File

@ -9,7 +9,7 @@ jest.mock("../device", () => ({
import * as React from "react";
import { ControlsPopup } from "../controls_popup";
import { mount } from "enzyme";
import { devices } from "../device";
import { getDevice } from "../device";
describe("<ControlsPopup />", () => {
beforeEach(function () {
@ -31,7 +31,7 @@ describe("<ControlsPopup />", () => {
});
it("x axis is inverted", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const { mock } = getDevice().moveRelative as jest.Mock<{}>;
const button = wrapper.find("button").first();
expect(button.props().title).toBe("move x axis");
button.simulate("click");
@ -42,7 +42,7 @@ describe("<ControlsPopup />", () => {
});
it("y axis is not inverted", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const { mock } = getDevice().moveRelative as jest.Mock<{}>;
const button = wrapper.find("button").at(2);
expect(button.props().title).toBe("move y axis");
button.simulate("click");
@ -53,7 +53,7 @@ describe("<ControlsPopup />", () => {
});
it("disabled when closed", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const { mock } = getDevice().moveRelative as jest.Mock<{}>;
wrapper.setState({ isOpen: false });
[0, 1, 2, 3].map((i) => wrapper.find("button").at(i).simulate("click"));
expect(mock.calls.length).toBe(0);

View File

@ -1,8 +1,8 @@
import { devices } from "../device";
import { setDevice, getDevice } from "../device";
import { dispatchNetworkUp, dispatchNetworkDown } from "./index";
import { Log } from "../interfaces";
import { ALLOWED_CHANNEL_NAMES, Farmbot, BotStateTree } from "farmbot";
import { get, set, throttle, noop } from "lodash";
import { get, throttle, noop } from "lodash";
import { success, error, info, warning } from "farmbot-toastr";
import { HardwareState } from "../devices/interfaces";
import { GetState } from "../redux/interfaces";
@ -27,7 +27,7 @@ let NEED_VERSION_CHECK = true;
type ConnectDeviceReturn = {} | ((dispatch: Function) => void);
const BAD_WORDS = ["WPA", "PSK", "PASSWORD", "NERVES"];
let alreadyToldYou = false;
const mq = "user.mqtt";
const secure = location.protocol === "https:";
/** Action creator that is called when FarmBot OS emits a status update.
* Coordinate updates, movement, etc.*/
@ -70,8 +70,7 @@ const bothUp = () => {
function readStatus() {
const noun = "'Read Status' command";
return devices
.current
return getDevice()
.readStatus()
.then(() => { commandOK(noun); }, () => { });
}
@ -104,8 +103,8 @@ const onStatus = (dispatch: Function, getState: GetState) =>
const onSent = (/** The MQTT Client Object (bot.client) */ client: {}) =>
(any: {}) => {
const netState = (get(client, "connected", false));
netState ? dispatchNetworkUp(mq) : dispatchNetworkDown(mq);
get(client, "connected", false) ?
dispatchNetworkUp("user.mqtt") : dispatchNetworkDown("user.mqtt");
};
const onLogs = (dispatch: Function) => (msg: Log) => {
@ -140,30 +139,25 @@ function onMalformed() {
}
}
const bootstrapAllTheThings =
const attachEventListeners =
(bot: Farmbot, dispatch: Function, getState: GetState) => () => {
devices.online = true;
devices.current = bot;
readStatus().then(changeLastClientConnected(bot), noop);
bot.on("online", onOnline);
bot.on("offline", onOffline);
bot.on("sent", onSent(bot.client));
bot.on("logs", onLogs(dispatch));
bot.on("status", onStatus(dispatch, getState));
bot.on("malformed", onMalformed);
readStatus().then(changeLastClientConnected(bot), noop);
set(window, "current_bot", bot);
};
const onOnline = () => dispatchNetworkUp("user.mqtt");
const doConnect = (dispatch: Function, getState: GetState) =>
({
token }: { token: Token }) => {
const secure = location.protocol === "https:";
const bot = new Farmbot({ token: token.encoded, secure });
bot.on("online", onOnline);
bot.on("offline", onOffline);
({ token }: { token: Token }) => {
const bot = setDevice(new Farmbot({ token: token.encoded, secure }));
return bot
.connect()
.then(bootstrapAllTheThings(bot, dispatch, getState), noop);
.then(attachEventListeners(bot, dispatch, getState), onOffline);
};
export function connectDevice(oldToken: string): ConnectDeviceReturn {
@ -174,3 +168,6 @@ export function connectDevice(oldToken: string): ConnectDeviceReturn {
ath ? (maybeRefreshToken(ath).then(ok)) : bail(AUTH_NOT_READY);
};
}
// 1. Refresh the token, maybe.
//

View File

@ -12,7 +12,7 @@ import * as React from "react";
import { mount } from "enzyme";
import { DirectionButton } from "../direction_button";
import { DirectionButtonProps } from "../interfaces";
import { devices } from "../../device";
import { getDevice } from "../../device";
describe("<DirectionButton/>", function () {
beforeEach(function () {
@ -28,14 +28,14 @@ describe("<DirectionButton/>", function () {
};
it("calls move command", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const { mock } = getDevice().moveRelative as jest.Mock<{}>;
const btn = mount(<DirectionButton {...buttonProps} />);
btn.simulate("click");
expect(mock.calls.length).toEqual(1);
});
it("is disabled", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const { mock } = getDevice().moveRelative as jest.Mock<{}>;
buttonProps.disabled = true;
const btn = mount(<DirectionButton {...buttonProps} />);
btn.simulate("click");
@ -43,7 +43,7 @@ describe("<DirectionButton/>", function () {
});
it("call has correct args", () => {
const { mock } = devices.current.moveRelative as jest.Mock<{}>;
const { mock } = getDevice().moveRelative as jest.Mock<{}>;
const btn = mount(<DirectionButton {...buttonProps} />);
btn.simulate("click");
const argList = mock.calls[0][0];

View File

@ -13,7 +13,7 @@ import * as React from "react";
import { mount } from "enzyme";
import { JogButtons } from "../jog_buttons";
import { JogMovementControlsProps } from "../interfaces";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { bot } from "../../__test_support__/fake_state/bot";
describe("<JogButtons/>", function () {
@ -30,14 +30,14 @@ describe("<JogButtons/>", function () {
};
it("calls home command", () => {
const { mock } = devices.current.home as jest.Mock<{}>;
const { mock } = getDevice().home as jest.Mock<{}>;
const jogButtons = mount(<JogButtons {...jogButtonProps} />);
jogButtons.find("button").at(3).simulate("click");
expect(mock.calls.length).toEqual(1);
});
it("is disabled", () => {
const { mock } = devices.current.home as jest.Mock<{}>;
const { mock } = getDevice().home as jest.Mock<{}>;
jogButtonProps.disabled = true;
const jogButtons = mount(<JogButtons {...jogButtonProps} />);
jogButtons.find("button").at(3).simulate("click");
@ -45,7 +45,7 @@ describe("<JogButtons/>", function () {
});
it("call has correct args", () => {
const { mock } = devices.current.home as jest.Mock<{}>;
const { mock } = getDevice().home as jest.Mock<{}>;
const jogButtons = mount(<JogButtons {...jogButtonProps} />);
jogButtons.find("button").at(3).simulate("click");
const argList = mock.calls[0][0];
@ -54,7 +54,7 @@ describe("<JogButtons/>", function () {
});
it("takes photo", () => {
const takePhoto = devices.current.takePhoto as jest.Mock<{}>;
const takePhoto = getDevice().takePhoto as jest.Mock<{}>;
const jogButtons = mount(<JogButtons {...jogButtonProps} />);
jogButtons.find("button").at(0).simulate("click");
expect(takePhoto).toHaveBeenCalled();

View File

@ -2,7 +2,7 @@ import * as React from "react";
import { DirectionButton } from "./direction_button";
import { homeAll } from "../devices/actions";
import { JogMovementControlsProps } from "./interfaces";
import { devices } from "../device";
import { getDevice } from "../device";
export class JogButtons extends React.Component<JogMovementControlsProps, {}> {
render() {
@ -12,7 +12,7 @@ export class JogButtons extends React.Component<JogMovementControlsProps, {}> {
<td>
<button
className="i fa fa-camera arrow-button fb-button"
onClick={() => devices.current.takePhoto()} />
onClick={() => getDevice().takePhoto()} />
</td>
<td />
<td />

View File

@ -11,7 +11,7 @@ import { mount } from "enzyme";
import { PeripheralList } from "../peripheral_list";
import { TaggedPeripheral } from "../../../resources/tagged_resources";
import { Pins } from "farmbot/dist";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("<PeripheralList/>", function () {
beforeEach(function () {
@ -73,7 +73,7 @@ describe("<PeripheralList/>", function () {
});
it("toggles pins", () => {
const { mock } = devices.current.togglePin as jest.Mock<{}>;
const { mock } = getDevice().togglePin as jest.Mock<{}>;
const wrapper = mount(<PeripheralList dispatch={() => { }}
peripherals={peripherals}
pins={pins}
@ -88,7 +88,7 @@ describe("<PeripheralList/>", function () {
});
it("pins toggles are disabled", () => {
const { mock } = devices.current.togglePin as jest.Mock<{}>;
const { mock } = getDevice().togglePin as jest.Mock<{}>;
const wrapper = mount(<PeripheralList dispatch={() => { }}
peripherals={peripherals}
pins={pins}

View File

@ -1,25 +1,12 @@
import { Farmbot } from "farmbot";
import { bail } from "./util";
import { set } from "lodash";
interface Devices {
online: boolean;
current: Farmbot;
let device: Farmbot;
export const getDevice = (): Farmbot => (device || bail("NO DEVICE SET"));
export function setDevice(bot: Farmbot): Farmbot {
set(window, "current_bot", bot);
return device = bot;
}
function NullBot(): Farmbot {
// Allow me to explain: I'm following the null object pattern to prevent nil
// checks all over the app. That way, all of our "if undefined" logic is in
// one place and NullBot satisfies the same interface as a real bot.
const funnyConfigObject = {
token: `0.${btoa("\"NOT_SET\"")}.0`,
secure: false
};
let bot = new Farmbot(funnyConfigObject);
bot.connect = () => Promise.reject(`Tried to connect to null bot.
You probably meant to set a bot first.`);
return bot;
}
export var devices: Devices = {
online: false,
current: NullBot()
};

View File

@ -21,7 +21,7 @@ const mockInfo = jest.fn();
jest.mock("farmbot-toastr", () => ({ success: mockOk, info: mockInfo }));
import * as actions from "../actions";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { fakeSequence } from "../../__test_support__/fake_state/resources";
import { fakeState } from "../../__test_support__/fake_state";
import { setSyncStatus, changeStepSize } from "../actions";
@ -34,7 +34,7 @@ describe("checkControllerUpdates()", function () {
});
it("calls checkUpdates", async () => {
const { mock } = devices.current.checkUpdates as jest.Mock<{}>;
const { mock } = getDevice().checkUpdates as jest.Mock<{}>;
await actions.checkControllerUpdates();
expect(mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
@ -47,7 +47,7 @@ describe("powerOff()", function () {
});
it("calls powerOff", async () => {
const { mock } = devices.current.powerOff as jest.Mock<{}>;
const { mock } = getDevice().powerOff as jest.Mock<{}>;
await actions.powerOff();
expect(mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
@ -60,7 +60,7 @@ describe("reboot()", function () {
});
it("calls reboot", async () => {
const { mock } = devices.current.reboot as jest.Mock<{}>;
const { mock } = getDevice().reboot as jest.Mock<{}>;
await actions.reboot();
expect(mock.calls.length).toEqual(1);
expect(mockOk.mock.calls.length).toEqual(1);
@ -73,13 +73,13 @@ describe("emergencyLock() / emergencyUnlock", function () {
});
it("calls emergencyLock", () => {
const { mock } = devices.current.emergencyLock as jest.Mock<{}>;
const { mock } = getDevice().emergencyLock as jest.Mock<{}>;
actions.emergencyLock();
expect(mock.calls.length).toEqual(1);
});
it("calls emergencyUnlock", () => {
const { mock } = devices.current.emergencyUnlock as jest.Mock<{}>;
const { mock } = getDevice().emergencyUnlock as jest.Mock<{}>;
window.confirm = jest.fn(() => true);
actions.emergencyUnlock();
expect(mock.calls.length).toEqual(1);
@ -92,7 +92,7 @@ describe("sync()", function () {
});
it("doesn't call sync: disconnected", () => {
const { mock } = devices.current.sync as jest.Mock<{}>;
const { mock } = getDevice().sync as jest.Mock<{}>;
const getState = () => fakeState();
actions.sync()(jest.fn(), getState);
expect(mock.calls.length).toEqual(0);
@ -107,7 +107,7 @@ describe("execSequence()", function () {
});
it("calls execSequence", async () => {
const { mock } = devices.current.execSequence as jest.Mock<{}>;
const { mock } = getDevice().execSequence as jest.Mock<{}>;
const s = fakeSequence().body;
await actions.execSequence(s);
expect(mock.calls.length).toEqual(1);
@ -116,7 +116,7 @@ describe("execSequence()", function () {
});
it("implodes when executing unsaved sequences", () => {
const { mock } = devices.current.execSequence as jest.Mock<{}>;
const { mock } = getDevice().execSequence as jest.Mock<{}>;
const ok = fakeSequence().body;
ok.id = undefined;
expect(() => actions.execSequence(ok)).toThrow();
@ -130,7 +130,7 @@ describe("MCUFactoryReset()", function () {
});
it("calls resetMCU", () => {
const { mock } = devices.current.resetMCU as jest.Mock<{}>;
const { mock } = getDevice().resetMCU as jest.Mock<{}>;
actions.MCUFactoryReset();
expect(mock.calls.length).toEqual(1);
});
@ -142,7 +142,7 @@ describe("botConfigChange()", function () {
});
it("calls updateMcu", async () => {
const { mock } = devices.current.updateMcu as jest.Mock<{}>;
const { mock } = getDevice().updateMcu as jest.Mock<{}>;
await actions.botConfigChange("encoder_enabled_x", 0);
expect(mock.calls.length).toEqual(1);
expect(mock.calls[0][0]).toEqual({ "encoder_enabled_x": 0 });
@ -156,7 +156,7 @@ describe("pinToggle()", function () {
});
it("calls togglePin", async () => {
const { mock } = devices.current.togglePin as jest.Mock<{}>;
const { mock } = getDevice().togglePin as jest.Mock<{}>;
await actions.pinToggle(5);
expect(mock.calls.length).toEqual(1);
const argList = mock.calls[0];
@ -171,7 +171,7 @@ describe("homeAll()", function () {
});
it("calls home", async () => {
const { mock } = devices.current.home as jest.Mock<{}>;
const { mock } = getDevice().home as jest.Mock<{}>;
await actions.homeAll(100);
expect(mock.calls.length).toEqual(1);
const argList = mock.calls[0];

View File

@ -2,7 +2,7 @@ import { t } from "i18next";
import axios from "axios";
import * as _ from "lodash";
import { success, warning, info, error } from "farmbot-toastr";
import { devices } from "../device";
import { getDevice } from "../device";
import { Log, Everything } from "../interfaces";
import { GithubRelease, MoveRelProps } from "./interfaces";
import { Thunk, GetState } from "../redux/interfaces";
@ -43,16 +43,14 @@ export const commandOK = (noun = "Command") => () => {
export function checkControllerUpdates() {
const noun = "Check for Updates";
devices
.current
getDevice()
.checkUpdates()
.then(commandOK(noun), commandErr(noun));
}
export function powerOff() {
const noun = "Power Off Bot";
devices
.current
getDevice()
.powerOff()
.then(commandOK(noun), commandErr(noun));
}
@ -61,23 +59,19 @@ export function factoryReset() {
if (!confirm(t(Content.FACTORY_RESET_ALERT))) {
return;
}
devices
.current
.resetOS();
getDevice().resetOS();
}
export function reboot() {
const noun = "Reboot Bot";
devices
.current
getDevice()
.reboot()
.then(commandOK(noun), commandErr(noun));
}
export function emergencyLock() {
const noun = "Emergency stop";
devices
.current
getDevice()
.emergencyLock()
.then(commandOK(noun), commandErr(noun));
}
@ -85,8 +79,7 @@ export function emergencyLock() {
export function emergencyUnlock() {
const noun = "Emergency unlock";
if (confirm(`Are you sure you want to unlock the device?`)) {
devices
.current
getDevice()
.emergencyUnlock()
.then(commandOK(noun), commandErr(noun));
}
@ -102,8 +95,7 @@ export function sync(): Thunk {
.controller_version, EXPECTED_MAJOR, EXPECTED_MINOR);
if (IS_OK) {
dispatch(setSyncStatus("syncing"));
devices
.current
getDevice()
.sync()
.then(() => {
commandOK(noun);
@ -129,8 +121,7 @@ export function sync(): Thunk {
export function execSequence(sequence: Sequence) {
const noun = "Sequence execution";
if (sequence.id) {
return devices
.current
return getDevice()
.execSequence(sequence.id)
.then(commandOK(noun), commandErr(noun));
} else {
@ -181,14 +172,13 @@ export function toggleControlPanel(payload: keyof ControlPanelState) {
}
export function MCUFactoryReset() {
return devices.current.resetMCU();
return getDevice().resetMCU();
}
export function botConfigChange(key: ConfigKey, value: number) {
const noun = "Setting toggle";
return devices
.current
return getDevice()
.updateMcu({ [key]: value })
.then(_.noop, commandErr(noun));
}
@ -198,8 +188,7 @@ export function settingToggle(
) {
if (displayAlert) { alert(displayAlert.replace(/\s+/g, " ")); }
const noun = "Setting toggle";
return devices
.current
return getDevice()
.updateMcu({
[name]: ((bot.hardware.mcu_params)[name] === 0) ? ON : OFF
})
@ -207,32 +196,28 @@ export function settingToggle(
}
export function moveRelative(props: MoveRelProps) {
return devices
.current
return getDevice()
.moveRelative(props)
.then(_.noop, commandErr("Relative movement"));
}
export function moveAbs(props: MoveRelProps) {
const noun = "Absolute movement";
return devices
.current
return getDevice()
.moveAbsolute(props)
.then(_.noop, commandErr(noun));
}
export function pinToggle(pin_number: number) {
const noun = "Setting toggle";
return devices
.current
return getDevice()
.togglePin({ pin_number })
.then(_.noop, commandErr(noun));
}
export function homeAll(speed: number) {
const noun = "'Home All' command";
devices
.current
getDevice()
.home({ axis: "all", speed })
.then(commandOK(noun), commandErr(noun));
}
@ -261,8 +246,7 @@ export function updateMCU(key: ConfigKey, val: string) {
function proceed() {
dispatch(startUpdate());
devices
.current
getDevice()
.updateMcu({ [key]: val })
.then(() => updateOK(dispatch, noun))
.catch(() => updateNO(dispatch, noun));
@ -278,8 +262,7 @@ export function updateMCU(key: ConfigKey, val: string) {
export function updateConfig(config: Configuration) {
const noun = "Update Config";
return function (dispatch: Function) {
devices
.current
getDevice()
.updateConfig(config)
.then(() => updateOK(dispatch, noun))
.catch(() => updateNO(dispatch, noun));

View File

@ -15,7 +15,7 @@ jest.mock("farmbot-toastr", () => ({
import * as React from "react";
import { mount, shallow } from "enzyme";
import { BoardType } from "../board_type";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("<BoardType/>", () => {
it("Farmduino", () => {
@ -49,7 +49,7 @@ describe("<BoardType/>", () => {
});
it("calls updateConfig", () => {
const updateConfig = devices.current.updateConfig as jest.Mock<{}>;
const updateConfig = getDevice().updateConfig as jest.Mock<{}>;
const wrapper = shallow(<BoardType
firmwareVersion={"Arduino Disconnected!"} />);
wrapper.find("FBSelect").simulate("change",

View File

@ -9,14 +9,14 @@ import * as React from "react";
import { mount } from "enzyme";
import { CalibrationRow } from "../calibration_row";
import { bot } from "../../../__test_support__/fake_state/bot";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("<HomingRow />", () => {
beforeEach(function () {
jest.clearAllMocks();
});
it("calls device", () => {
const { mock } = devices.current.calibrate as jest.Mock<{}>;
const { mock } = getDevice().calibrate as jest.Mock<{}>;
const result = mount(<CalibrationRow hardware={bot.hardware.mcu_params} />);
result.find("LockableButton").at(0).simulate("click");
result.find("LockableButton").at(1).simulate("click");

View File

@ -11,7 +11,7 @@ jest.mock("farmbot-toastr", () => ({ info: mockInfo, error: mockError }));
import * as React from "react";
import { mount, shallow } from "enzyme";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
import { CameraSelection } from "../camera_selection";
describe("<CameraSelection/>", () => {
@ -32,7 +32,7 @@ describe("<CameraSelection/>", () => {
});
it("changes camera", () => {
const { mock } = devices.current.setUserEnv as jest.Mock<{}>;
const { mock } = getDevice().setUserEnv as jest.Mock<{}>;
const cameraSelection = shallow(<CameraSelection
env={{}} />);
cameraSelection.find("FBSelect")

View File

@ -9,7 +9,7 @@ import * as React from "react";
import { mount } from "enzyme";
import { HomingRow } from "../homing_row";
import { bot } from "../../../__test_support__/fake_state/bot";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("<HomingRow />", () => {
beforeEach(function () {
@ -26,7 +26,7 @@ describe("<HomingRow />", () => {
});
});
it("calls device", () => {
const { mock } = devices.current.findHome as jest.Mock<{}>;
const { mock } = getDevice().findHome as jest.Mock<{}>;
const result = mount(<HomingRow hardware={bot.hardware.mcu_params} />);
result.find("LockableButton").at(0).simulate("click");
result.find("LockableButton").at(1).simulate("click");

View File

@ -12,7 +12,7 @@ import * as React from "react";
import { OsUpdateButton } from "../os_update_button";
import { mount } from "enzyme";
import { bot } from "../../../__test_support__/fake_state/bot";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("<OsUpdateButton/>", () => {
beforeEach(function () {
@ -40,7 +40,7 @@ describe("<OsUpdateButton/>", () => {
expect(osUpdateButton.text()).toBe("UPDATE");
});
it("calls checkUpdates", () => {
const { mock } = devices.current.checkUpdates as jest.Mock<{}>;
const { mock } = getDevice().checkUpdates as jest.Mock<{}>;
const buttons = mount(<OsUpdateButton bot={bot} />);
const osUpdateButton = buttons.find("button").last();
osUpdateButton.simulate("click");
@ -85,7 +85,7 @@ describe("<OsUpdateButton/>", () => {
expect(osUpdateButton.text()).toBe("UPDATE");
});
it("is disabled", () => {
const { mock } = devices.current.checkUpdates as jest.Mock<{}>;
const { mock } = getDevice().checkUpdates as jest.Mock<{}>;
bot.hardware.jobs = { "FBOS_OTA": { status: "working", percent: 10, unit: "percent" } };
const buttons = mount(<OsUpdateButton bot={bot} />);
const osUpdateButton = buttons.find("button").last();

View File

@ -8,14 +8,14 @@ jest.mock("../../../device", () => ({
import * as React from "react";
import { mount } from "enzyme";
import { ZeroRow } from "../zero_row";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("<HomingRow />", () => {
beforeEach(function () {
jest.clearAllMocks();
});
it("calls device", () => {
const { mock } = devices.current.setZero as jest.Mock<{}>;
const { mock } = getDevice().setZero as jest.Mock<{}>;
const result = mount(<ZeroRow />);
result.find("ZeroButton").at(0).simulate("click");
result.find("ZeroButton").at(1).simulate("click");

View File

@ -2,7 +2,7 @@ import * as React from "react";
import { Row, Col, DropDownItem } from "../../ui/index";
import { t } from "i18next";
import { FBSelect } from "../../ui/new_fb_select";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { info, error } from "farmbot-toastr";
import { FirmwareHardware } from "farmbot";
@ -70,8 +70,7 @@ export class BoardType
const firmware_hardware = selectedBoard.value;
if (selectedBoard && isFwHardwareValue(firmware_hardware)) {
info(t("Sending firmware configuration..."), t("Sending"));
devices
.current
getDevice()
.updateConfig({ firmware_hardware })
.catch(() => error(t("An error occurred during configuration.")));
}

View File

@ -1,6 +1,6 @@
import * as React from "react";
import { t } from "i18next";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { Axis } from "../interfaces";
import { LockableButton } from "./lockable_button";
import { axisTrackingStatus } from "./axis_tracking_status";
@ -9,8 +9,7 @@ import { Row, Col } from "../../ui/index";
import { CalibrationRowProps } from "./interfaces";
function calibrate(axis: Axis) {
devices
.current
getDevice()
.calibrate({ axis });
}

View File

@ -4,7 +4,7 @@ import { t } from "i18next";
import { CameraSelectionProps, CameraSelectionState } from "../interfaces";
import { DropDownItem } from "../../ui/index";
import { info, success, error } from "farmbot-toastr/dist";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { FBSelect } from "../../ui/new_fb_select";
const CAMERA_CHOICES = [
@ -42,8 +42,7 @@ export class CameraSelection
sendOffConfig = (selectedCamera: DropDownItem) => {
const message = { "camera": JSON.stringify(selectedCamera.value) };
info(t("Sending camera configuration..."), t("Sending"));
devices
.current
getDevice()
.setUserEnv(message)
.then(() => {
success(t("Successfully configured camera!"));

View File

@ -1,6 +1,6 @@
import * as React from "react";
import { t } from "i18next";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { Axis } from "../interfaces";
import { HomingRowProps } from "./interfaces";
import { Farmbot } from "farmbot/dist";
@ -11,7 +11,7 @@ import { SpacePanelToolTip } from "./space_panel_tool_tip";
import { Row, Col } from "../../ui/index";
const speed = Farmbot.defaults.speed;
const findHome = (axis: Axis) => devices.current.findHome({ speed, axis });
const findHome = (axis: Axis) => getDevice().findHome({ speed, axis });
export function HomingRow(props: HomingRowProps) {
const { hardware } = props;

View File

@ -1,11 +1,11 @@
import * as React from "react";
import { t } from "i18next";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { Axis } from "../interfaces";
import { ToolTips } from "../../constants";
import { Row, Col } from "../../ui/index";
const zero = (axis: Axis) => devices.current.setZero(axis);
const zero = (axis: Axis) => getDevice().setZero(axis);
const AXES: Axis[] = ["x", "y", "z"];
export function ZeroButton({ axis }: { axis: Axis }) {

View File

@ -12,7 +12,7 @@ import {
import { Diagnosis, DiagnosisName } from "./connectivity/diagnosis";
import { StatusRowProps } from "./connectivity/connectivity_row";
import { refresh } from "../api/crud";
import { devices } from "../device";
import { getDevice } from "../device";
@connect(mapStateToProps)
export class Devices extends React.Component<Props, {}> {
@ -45,7 +45,7 @@ export class Devices extends React.Component<Props, {}> {
refresh = () => {
this.props.dispatch(refresh(this.props.deviceAccount));
devices.current.getState();
getDevice().getState();
};
render() {

View File

@ -9,7 +9,7 @@ jest.mock("../../device", () => ({
import * as React from "react";
import { mount } from "enzyme";
import { FarmwareForms } from "../farmware_forms";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { FarmwareManifest, Dictionary } from "farmbot";
function fakeFarmwares(): Dictionary<FarmwareManifest | undefined> {
@ -43,7 +43,7 @@ describe("<FarmwareForms/>", () => {
});
it("runs", () => {
const runFarmware = devices.current.execScript as jest.Mock<{}>;
const runFarmware = getDevice().execScript as jest.Mock<{}>;
const wrapper = mount(<FarmwareForms farmwares={fakeFarmwares()} />);
const run = wrapper.find("button").first();
run.simulate("click");

View File

@ -11,7 +11,7 @@ jest.mock("../../device", () => ({
import * as React from "react";
import { mount } from "enzyme";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { FarmwarePanel } from "../farmware_panel";
describe("<FarmwarePanel/>", () => {
@ -29,7 +29,7 @@ describe("<FarmwarePanel/>", () => {
}
it("calls install", () => {
const { mock } = devices.current.installFarmware as jest.Mock<{}>;
const { mock } = getDevice().installFarmware as jest.Mock<{}>;
const panel = bootstrapTest();
const buttons = panel.component.find("button");
expect(buttons.at(0).text()).toEqual("Install");
@ -40,7 +40,7 @@ describe("<FarmwarePanel/>", () => {
});
it("calls update", () => {
const { mock } = devices.current.updateFarmware as jest.Mock<{}>;
const { mock } = getDevice().updateFarmware as jest.Mock<{}>;
const panel = bootstrapTest();
const buttons = panel.component.find("button");
expect(buttons.at(3).text()).toEqual("Update");
@ -51,7 +51,7 @@ describe("<FarmwarePanel/>", () => {
});
it("calls remove", () => {
const { mock } = devices.current.removeFarmware as jest.Mock<{}>;
const { mock } = getDevice().removeFarmware as jest.Mock<{}>;
const panel = bootstrapTest();
const buttons = panel.component.find("button");
expect(buttons.at(2).text()).toEqual("Remove");
@ -62,7 +62,7 @@ describe("<FarmwarePanel/>", () => {
});
it("calls run", () => {
const { mock } = devices.current.execScript as jest.Mock<{}>;
const { mock } = getDevice().execScript as jest.Mock<{}>;
const panel = bootstrapTest();
const buttons = panel.component.find("button");
expect(buttons.at(4).text()).toEqual("Run");

View File

@ -7,14 +7,14 @@ jest.mock("../../../device", () => ({
}));
import { calibrate, scanImage } from "../actions";
import { devices } from "../../../device";
import { getDevice } from "../../../device";
describe("scanImage()", () => {
beforeEach(function () {
jest.clearAllMocks();
});
it("calls out to the device", () => {
const { mock } = devices.current.execScript as jest.Mock<{}>;
const { mock } = getDevice().execScript as jest.Mock<{}>;
// Run function to invoke side effects
const thunk = scanImage(4);
thunk();
@ -35,7 +35,7 @@ describe("calibrate()", () => {
jest.clearAllMocks();
});
it("calls out to the device", () => {
const { mock } = devices.current.execScript as jest.Mock<{}>;
const { mock } = getDevice().execScript as jest.Mock<{}>;
// Run function to invoke side effects
const thunk = calibrate();
thunk();

View File

@ -1,15 +1,14 @@
import { devices } from "../../device";
import { getDevice } from "../../device";
export function calibrate() {
return function () {
devices.current.execScript("camera-calibration");
getDevice().execScript("camera-calibration");
};
}
export function scanImage(imageId: number) {
return function () {
devices
.current
getDevice()
.execScript("historical-camera-calibration", [{
kind: "pair", args: {
label: "CAMERA_CALIBRATION_selected_image",

View File

@ -3,7 +3,7 @@ import { Widget, WidgetHeader, WidgetBody, Col } from "../ui/index";
import { t } from "i18next";
import { FarmwareManifest, Dictionary } from "farmbot";
import { betterCompact } from "../util";
import { devices } from "../device";
import { getDevice } from "../device";
interface FarmwareFormsProps {
farmwares: Dictionary<FarmwareManifest | undefined>;
@ -38,7 +38,7 @@ export function FarmwareForms(props: FarmwareFormsProps): JSX.Element {
+ farmware.meta.version : ""}>
<button
className="fb-button gray"
onClick={() => devices.current.execScript(farmware.name)}>
onClick={() => getDevice().execScript(farmware.name)}>
{t("Run")}
</button>
</WidgetHeader>

View File

@ -1,7 +1,7 @@
import * as React from "react";
import * as _ from "lodash";
import { t } from "i18next";
import { devices } from "../device";
import { getDevice } from "../device";
import { FWProps, FWState } from "./interfaces";
import { MustBeOnline } from "../devices/must_be_online";
import { ToolTips } from "../constants";
@ -30,32 +30,28 @@ export class FarmwarePanel extends React.Component<FWProps, Partial<FWState>> {
update = () => {
this
.ifFarmwareSelected(label => devices
.current
.ifFarmwareSelected(label => getDevice()
.updateFarmware(label)
.then(() => this.setState({ selectedFarmware: undefined })));
}
remove = () => {
this
.ifFarmwareSelected(label => devices
.current
.ifFarmwareSelected(label => getDevice()
.removeFarmware(label)
.then(() => this.setState({ selectedFarmware: undefined })));
}
run = () => {
this
.ifFarmwareSelected(label => devices
.current
.ifFarmwareSelected(label => getDevice()
.execScript(label)
.then(() => this.setState({ selectedFarmware: label })));
}
install = () => {
if (this.state.packageUrl) {
devices
.current
getDevice()
.installFarmware(this.state.packageUrl)
.then(() => this.setState({ packageUrl: "" }));
} else {

View File

@ -6,7 +6,7 @@ import { success, error } from "farmbot-toastr";
import { Widget, WidgetHeader, WidgetBody } from "../../ui/index";
import { ImageFlipper } from "./image_flipper";
import { PhotosProps } from "./interfaces";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { ToolTips } from "../../constants";
import { selectImage } from "./actions";
import { WidgetFooter } from "../../ui/widget_footer";
@ -39,7 +39,7 @@ export class Photos extends React.Component<PhotosProps, {}> {
takePhoto = () => {
const ok = () => success(t("Processing now. Refresh page to see result."));
const no = () => error(t("Error taking photo"));
devices.current.takePhoto().then(ok, no);
getDevice().takePhoto().then(ok, no);
}
metaDatas() {

View File

@ -8,7 +8,7 @@ jest.mock("../../../device", () => {
}
};
});
import { devices } from "../../../device";
import { getDevice } from "../../../device";
import { translateImageWorkspaceAndSave } from "../actions";
import { scanImage, test } from "../actions";
@ -31,8 +31,8 @@ describe("actions", () => {
"V_LO": "WEED_DETECTOR_V_LO"
});
translator("H_HI", 45);
expect(devices.current.setUserEnv).toHaveBeenCalledTimes(1);
expect(devices.current.setUserEnv)
expect(getDevice().setUserEnv).toHaveBeenCalledTimes(1);
expect(getDevice().setUserEnv)
.toHaveBeenLastCalledWith({ "WEED_DETECTOR_H_HI": "45" });
});
});
@ -42,7 +42,7 @@ describe("scanImage()", () => {
jest.clearAllMocks();
});
it("calls out to the device", () => {
const { mock } = devices.current.execScript as jest.Mock<{}>;
const { mock } = getDevice().execScript as jest.Mock<{}>;
// Run function to invoke side effects
const thunk = scanImage(5);
thunk();
@ -63,7 +63,7 @@ describe("test()", () => {
jest.clearAllMocks();
});
it("calls out to the device", () => {
const { mock } = devices.current.execScript as jest.Mock<{}>;
const { mock } = getDevice().execScript as jest.Mock<{}>;
// Run function to invoke side effects
const thunk = test();
thunk();

View File

@ -6,7 +6,7 @@ import { Thunk } from "../../redux/interfaces";
import { API } from "../../api";
import { Progress, ProgressCallback, HttpData } from "../../util";
import { GenericPointer } from "../../interfaces";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { WDENVKey } from "./remote_env/interfaces";
import { NumericValues } from "./image_workspace";
import { envSave } from "./remote_env/actions";
@ -64,8 +64,7 @@ const label = "PLANT_DETECTION_selected_image";
export function scanImage(imageId: number) {
return function () {
devices
.current
getDevice()
.execScript("historical-plant-detection", [{
kind: "pair", args: { label: label, value: "" + imageId }
}]);
@ -74,6 +73,6 @@ export function scanImage(imageId: number) {
export function test() {
return function () {
devices.current.execScript("plant-detection");
getDevice().execScript("plant-detection");
};
}

View File

@ -2,7 +2,7 @@ import * as React from "react";
import { connect } from "react-redux";
import { DetectorState, HSV } from "./interfaces";
import { TitleBar } from "./title";
import { devices } from "../../device";
import { getDevice } from "../../device";
import { Row, Col, Widget, WidgetBody } from "../../ui/index";
import { t } from "i18next";
import { resetWeedDetection, scanImage, test } from "./actions";
@ -41,7 +41,7 @@ export class WeedDetector
};
test = () => {
devices.current.execScript("plant-detection");
getDevice().execScript("plant-detection");
}
/** Maps <ImageWorkspace/> props to weed detector ENV vars. */

View File

@ -8,7 +8,7 @@ jest.mock("../../../../device", () => {
};
});
import { envSave } from "../actions";
import { devices } from "../../../../device";
import { getDevice } from "../../../../device";
describe("actions", () => {
it("Saves environment variables", () => {
@ -16,8 +16,8 @@ describe("actions", () => {
* triggering side effects. */
jest.clearAllMocks();
envSave("CAMERA_CALIBRATION_blur", 24);
expect(devices.current.setUserEnv).toHaveBeenCalledTimes(1);
expect(devices.current.setUserEnv)
expect(getDevice().setUserEnv).toHaveBeenCalledTimes(1);
expect(getDevice().setUserEnv)
.toHaveBeenLastCalledWith({ "CAMERA_CALIBRATION_blur": "24" });
});
});

View File

@ -1,10 +1,9 @@
import { devices } from "../../../device";
import { getDevice } from "../../../device";
import { WDENVKey } from "./interfaces";
import { formatEnvKey } from "./translators";
/** Send a number to FBOS for storage on the device. */
export function envSave(key: WDENVKey, value: number) {
devices
.current
getDevice()
.setUserEnv({ [key]: JSON.stringify(formatEnvKey(key, value)) });
}

View File

@ -1,5 +1,5 @@
import { ResourceName, DataChangeType, Dictionary } from "farmbot/dist";
import { devices } from "./device";
import { getDevice } from "./device";
import { box } from "boxed_value";
import * as _ from "lodash";
@ -23,7 +23,7 @@ export function notifyBotOfChanges(url: string | undefined, action: DataChangeTy
url.split("/").filter((chunk: ResourceName) => {
return RESOURCES.includes(chunk);
}).map(async function (resource: ResourceName) {
devices.current.dataUpdate(action, { [resource]: inferUpdateId(url) });
getDevice().dataUpdate(action, { [resource]: inferUpdateId(url) });
});
}
}