diff --git a/app/controllers/api/sensor_readings_controller.rb b/app/controllers/api/sensor_readings_controller.rb index a0e945873..65feb4c28 100644 --- a/app/controllers/api/sensor_readings_controller.rb +++ b/app/controllers/api/sensor_readings_controller.rb @@ -1,7 +1,10 @@ module Api class SensorReadingsController < Api::AbstractController + LIMIT = 5000 + before_action :clean_old + def create - mutate SensorReadings::Create.run(raw_json, device: current_device) + mutate SensorReadings::Create.run(raw_json, device: current_device) end def index @@ -17,10 +20,23 @@ module Api render json: "" end - private + private + + def clean_old + if current_device.sensor_readings.count > LIMIT + current_device + .sensor_readings + .where + .not(id: readings.pluck(:id)) + .delete_all + end + end def readings - SensorReading.where(device: current_device) + @readings ||= SensorReading + .where(device: current_device) + .order(created_at: :desc) + .limit(LIMIT) end def reading diff --git a/app/models/device.rb b/app/models/device.rb index f2ecf6521..750244f22 100644 --- a/app/models/device.rb +++ b/app/models/device.rb @@ -171,9 +171,10 @@ class Device < ApplicationRecord end TOO_MANY_CONNECTIONS = - "Your device is " + - "reconnecting to the server too often. Please " + - "see https://developer.farm.bot/docs/connectivity-issues" + "Your device is reconnecting to the server too often. " + + "This may be a sign of local network issues. " + + "Please review the documentation provided at " + + "https://software.farm.bot/docs/connecting-farmbot-to-the-internet" def self.connection_warning(username) device_id = username.split("_").last.to_i || 0 device = self.find_by(id: device_id) diff --git a/app/mutations/devices/create_seed_data.rb b/app/mutations/devices/create_seed_data.rb index 8cc336244..fb0899b39 100644 --- a/app/mutations/devices/create_seed_data.rb +++ b/app/mutations/devices/create_seed_data.rb @@ -7,7 +7,9 @@ module Devices "genesis_1.2" => Devices::Seeders::GenesisOneTwo, "genesis_1.3" => Devices::Seeders::GenesisOneThree, "genesis_1.4" => Devices::Seeders::GenesisOneFour, + "genesis_1.5" => Devices::Seeders::GenesisOneFive, "genesis_xl_1.4" => Devices::Seeders::GenesisXlOneFour, + "genesis_xl_1.5" => Devices::Seeders::GenesisXlOneFive, "demo_account" => Devices::Seeders::DemoAccountSeeder, "none" => Devices::Seeders::None, diff --git a/app/mutations/devices/seeders/genesis_one_five.rb b/app/mutations/devices/seeders/genesis_one_five.rb new file mode 100644 index 000000000..dde23e30d --- /dev/null +++ b/app/mutations/devices/seeders/genesis_one_five.rb @@ -0,0 +1,11 @@ +module Devices + module Seeders + class GenesisOneFive < AbstractGenesis + def settings_firmware + device + .fbos_config + .update!(firmware_hardware: FbosConfig::FARMDUINO_K15) + end + end + end +end diff --git a/app/mutations/devices/seeders/genesis_xl_one_five.rb b/app/mutations/devices/seeders/genesis_xl_one_five.rb new file mode 100644 index 000000000..b3e291a1f --- /dev/null +++ b/app/mutations/devices/seeders/genesis_xl_one_five.rb @@ -0,0 +1,23 @@ +module Devices + module Seeders + class GenesisXlOneFive < AbstractGenesis + def settings_firmware + device + .fbos_config + .update!(firmware_hardware: FbosConfig::FARMDUINO_K15) + end + + def settings_device_name + device.update!(name: "FarmBot Genesis XL") + end + + def settings_default_map_size_x + device.web_app_config.update!(map_size_x: 5_900) + end + + def settings_default_map_size_y + device.web_app_config.update!(map_size_y: 2_900) + end + end + end +end diff --git a/frontend/devices/components/fbos_settings/__tests__/fbos_details_test.tsx b/frontend/devices/components/fbos_settings/__tests__/fbos_details_test.tsx index f7cd59033..0c4cdb602 100644 --- a/frontend/devices/components/fbos_settings/__tests__/fbos_details_test.tsx +++ b/frontend/devices/components/fbos_settings/__tests__/fbos_details_test.tsx @@ -85,6 +85,26 @@ describe("", () => { expect(wrapper.text()).toContain("0.0.0"); }); + it("displays firmware commit link from firmware_commit", () => { + const p = fakeProps(); + const commit = "abcdefgh"; + p.botInfoSettings.firmware_commit = commit; + const wrapper = mount(); + expect(wrapper.find("a").last().text()).toEqual(commit); + expect(wrapper.find("a").last().props().href?.split("/").slice(-1)[0]) + .toEqual(commit); + }); + + it("displays firmware commit link from version", () => { + const p = fakeProps(); + const commit = "abcdefgh"; + p.botInfoSettings.firmware_version = `1.2.3.R.x-${commit}+`; + const wrapper = mount(); + expect(wrapper.find("a").last().text()).toEqual(commit); + expect(wrapper.find("a").last().props().href?.split("/").slice(-1)[0]) + .toEqual(commit); + }); + it("displays commit link", () => { const p = fakeProps(); p.botInfoSettings.commit = "abcdefgh"; diff --git a/frontend/devices/components/fbos_settings/fbos_details.tsx b/frontend/devices/components/fbos_settings/fbos_details.tsx index 9070b57cf..43ad6a0c7 100644 --- a/frontend/devices/components/fbos_settings/fbos_details.tsx +++ b/frontend/devices/components/fbos_settings/fbos_details.tsx @@ -260,6 +260,8 @@ export function FbosDetails(props: FbosDetailsProps) { wifi_level_percent, cpu_usage, private_ip, } = props.botInfoSettings; const { last_ota, last_ota_checkup } = props.deviceAccount.body; + const firmwareCommit = [firmware_commit, firmware_version].includes("---") + ? firmware_commit : firmware_version?.split("-")[1] || firmware_commit; return
{t("Local IP address")}: {private_ip}

}

{t("Firmware")}: {reformatFwVersion(firmware_version)}

+ repo={"farmbot-arduino-firmware"} commit={firmwareCommit} />

{t("Firmware code")}: {firmware_version}

{isNumber(uptime) && } {isNumber(memory_usage) && diff --git a/frontend/messages/cards.tsx b/frontend/messages/cards.tsx index 0dcf9cce9..8b03e50e5 100644 --- a/frontend/messages/cards.tsx +++ b/frontend/messages/cards.tsx @@ -23,7 +23,6 @@ import { import { updateConfig } from "../devices/actions"; import { fetchBulletinContent, seedAccount } from "./actions"; import { startCase } from "lodash"; -import { DevSettings } from "../account/dev/dev_support"; import { Session } from "../session"; export const AlertCard = (props: AlertCardProps) => { @@ -219,11 +218,11 @@ const SEED_DATA_OPTIONS = (): DropDownItem[] => [ { label: "Genesis v1.2", value: "genesis_1.2" }, { label: "Genesis v1.3", value: "genesis_1.3" }, { label: "Genesis v1.4", value: "genesis_1.4" }, + { label: "Genesis v1.5", value: "genesis_1.5" }, { label: "Genesis v1.4 XL", value: "genesis_xl_1.4" }, - ...(DevSettings.futureFeaturesEnabled() ? [ - { label: "Express v1.0", value: "express_1.0" }, - { label: "Express v1.0 XL", value: "express_xl_1.0" }, - ] : []), + { label: "Genesis v1.5 XL", value: "genesis_xl_1.5" }, + { label: "Express v1.0", value: "express_1.0" }, + { label: "Express v1.0 XL", value: "express_xl_1.0" }, { label: "Custom Bot", value: "none" }, ]; diff --git a/spec/controllers/api/devices/devices_controller_seed_spec.rb b/spec/controllers/api/devices/devices_controller_seed_spec.rb index ade9cf50d..259e07667 100644 --- a/spec/controllers/api/devices/devices_controller_seed_spec.rb +++ b/spec/controllers/api/devices/devices_controller_seed_spec.rb @@ -352,6 +352,50 @@ describe Api::DevicesController do expect(settings_default_map_size_y?(device)).to eq(1400) end + it "seeds accounts with Genesis 1.5 data" do + start_tests "genesis_1.5" + + expect(peripherals_lighting?(device).pin).to eq(7) + expect(peripherals_peripheral_4?(device).pin).to eq(10) + expect(peripherals_peripheral_5?(device).pin).to eq(12) + expect(peripherals_vacuum?(device).pin).to be(9) + expect(peripherals_water?(device).pin).to be(8) + expect(pin_bindings_button_1?(device).special_action).to eq("emergency_lock") + expect(pin_bindings_button_2?(device).special_action).to eq("emergency_unlock") + expect(plants?(device)).to be true + expect(sensors_soil_sensor?(device).pin).to eq(59) + expect(sensors_tool_verification?(device).pin).to eq(63) + expect(settings_device_name?(device)).to eq("FarmBot Genesis") + expect(settings_enable_encoders?(device)).to be(true) + expect(settings_firmware?(device)).to eq("farmduino_k15") + expect(settings_hide_sensors?(device)).to be(false) + expect(tool_slots_slot_1?(device).name).to eq("Seeder") + expect(tool_slots_slot_2?(device).name).to eq("Seed Bin") + expect(tool_slots_slot_3?(device).name).to eq("Seed Tray") + expect(tool_slots_slot_4?(device).name).to eq("Watering Nozzle") + expect(tool_slots_slot_5?(device).name).to eq("Soil Sensor") + expect(tool_slots_slot_6?(device).name).to eq("Weeder") + expect(tools_seed_bin?(device)).to be + expect(tools_seed_tray?(device)).to be + expect(tools_seed_trough_1?(device)).to_not be + expect(tools_seed_trough_2?(device)).to_not be + expect(tools_seed_trough_3?(device)).to_not be + expect(tools_seeder?(device)).to be_kind_of(Tool) + expect(tools_soil_sensor?(device)).to be_kind_of(Tool) + expect(tools_watering_nozzle?(device)).to be_kind_of(Tool) + expect(tools_weeder?(device)).to be_kind_of(Tool) + expect(sequences_mount_tool?(device)).to be + expect(sequences_pickup_seed_genesis?(device)).to be + expect(sequences_pickup_seed_express?(device)).to_not be + expect(sequences_plant_seed?(device)).to be_kind_of(Sequence) + expect(sequences_take_photo_of_plant?(device)).to be_kind_of(Sequence) + expect(sequences_tool_error?(device)).to be_kind_of(Sequence) + expect(sequences_unmount_tool?(device)).to be_kind_of(Sequence) + expect(sequences_water_plant?(device)).to be_kind_of(Sequence) + expect(settings_default_map_size_x?(device)).to eq(2900) + expect(settings_default_map_size_y?(device)).to eq(1400) + end + it "seeds accounts with Genesis XL 1.4 data" do start_tests "genesis_xl_1.4" @@ -404,6 +448,58 @@ describe Api::DevicesController do expect(settings_default_map_size_y?(device)).to eq(2900) end + it "seeds accounts with Genesis XL 1.5 data" do + start_tests "genesis_xl_1.5" + + expect(peripherals_lighting?(device).pin).to eq(7) + expect(peripherals_peripheral_4?(device).pin).to eq(10) + expect(peripherals_peripheral_5?(device).pin).to eq(12) + expect(peripherals_vacuum?(device).pin).to be(9) + expect(peripherals_water?(device).pin).to be(8) + expect(pin_bindings_button_1?(device).special_action).to eq("emergency_lock") + expect(pin_bindings_button_2?(device).special_action).to eq("emergency_unlock") + expect(plants?(device)).to be true + expect(sensors_soil_sensor?(device).pin).to eq(59) + expect(sensors_tool_verification?(device).pin).to eq(63) + expect(settings_device_name?(device)).to eq("FarmBot Genesis XL") + expect(settings_enable_encoders?(device)).to be(true) + expect(settings_firmware?(device)).to eq("farmduino_k15") + expect(settings_hide_sensors?(device)).to be(false) + expect(tool_slots_slot_1?(device).name).to eq("Seeder") + expect(tool_slots_slot_2?(device).name).to eq("Seed Bin") + expect(tool_slots_slot_3?(device).name).to eq("Seed Tray") + expect(tool_slots_slot_4?(device).name).to eq("Watering Nozzle") + expect(tool_slots_slot_5?(device).name).to eq("Soil Sensor") + expect(tool_slots_slot_6?(device).name).to eq("Weeder") + + check_slot_pairing(tool_slots_slot_1?(device), "Seeder") + check_slot_pairing(tool_slots_slot_2?(device), "Seed Bin") + check_slot_pairing(tool_slots_slot_3?(device), "Seed Tray") + check_slot_pairing(tool_slots_slot_4?(device), "Watering Nozzle") + check_slot_pairing(tool_slots_slot_5?(device), "Soil Sensor") + check_slot_pairing(tool_slots_slot_6?(device), "Weeder") + + expect(tools_seed_bin?(device)).to be + expect(tools_seed_tray?(device)).to be + expect(tools_seed_trough_1?(device)).to_not be + expect(tools_seed_trough_2?(device)).to_not be + expect(tools_seed_trough_3?(device)).to_not be + expect(tools_seeder?(device)).to be_kind_of(Tool) + expect(tools_soil_sensor?(device)).to be_kind_of(Tool) + expect(tools_watering_nozzle?(device)).to be_kind_of(Tool) + expect(tools_weeder?(device)).to be_kind_of(Tool) + expect(sequences_mount_tool?(device)).to be + expect(sequences_pickup_seed_genesis?(device)).to be + expect(sequences_pickup_seed_express?(device)).to_not be + expect(sequences_plant_seed?(device)).to be_kind_of(Sequence) + expect(sequences_take_photo_of_plant?(device)).to be_kind_of(Sequence) + expect(sequences_tool_error?(device)).to be_kind_of(Sequence) + expect(sequences_unmount_tool?(device)).to be_kind_of(Sequence) + expect(sequences_water_plant?(device)).to be_kind_of(Sequence) + expect(settings_default_map_size_x?(device)).to eq(5900) + expect(settings_default_map_size_y?(device)).to eq(2900) + end + it "seeds accounts with Express 1.0 data" do start_tests "express_1.0" diff --git a/spec/controllers/api/sensor_readings/controller_spec.rb b/spec/controllers/api/sensor_readings/controller_spec.rb index 19a1e8612..7f544917c 100644 --- a/spec/controllers/api/sensor_readings/controller_spec.rb +++ b/spec/controllers/api/sensor_readings/controller_spec.rb @@ -18,7 +18,7 @@ describe Api::SensorReadingsController do x: nil, y: 1, z: 2, - mode: 1 + mode: 1, }.to_json, params: { format: :json } @@ -40,7 +40,7 @@ describe Api::SensorReadingsController do y: 1, z: 2, mode: 1, - read_at: read_at + read_at: read_at, }.to_json, params: { format: :json } @@ -105,5 +105,23 @@ describe Api::SensorReadingsController do post :create, body: {}.to_json expect(response.status).to eq(401) end + + it "cleans up excess logs" do + const_reassign(Api::SensorReadingsController, :LIMIT, 5) + sign_in user + 10.times do |n| + FactoryBot.create(:sensor_reading, + device: user.device, + created_at: n.minutes.ago) + end + expect(user.device.sensor_readings.count).to eq(10) + get :index, params: { format: :json } + expect(json.count).to eq(5) + expect(user.device.sensor_readings.count).to eq(5) + const_reassign(Api::SensorReadingsController, :LIMIT, 5000) + first = (json.first[:created_at]) + last = (json.last[:created_at]) + expect(first).to be > last + end end end