diff --git a/_data/toc/v15.yml b/_data/toc/v15.yml index 6e33c4f..8849bfb 100644 --- a/_data/toc/v15.yml +++ b/_data/toc/v15.yml @@ -189,8 +189,6 @@ contents: url: interpolation - title: Track Movement url: track-movement - - title: OpenFarm - url: openfarm - title: Security Vulnerabilities url: responsible-disclosure-of-security-vulnerabilities - title: GitHub diff --git a/_redirects/openfarm.md b/_redirects/openfarm.md deleted file mode 100644 index f3ab941..0000000 --- a/_redirects/openfarm.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -permalink: /docs/openfarm -page_path: /other/openfarm -layout: redirect ---- diff --git a/v15/docs/farmbot-os/sidecar-hardware.md b/v15/docs/farmbot-os/sidecar-hardware.md index bf44086..29ad2fb 100644 --- a/v15/docs/farmbot-os/sidecar-hardware.md +++ b/v15/docs/farmbot-os/sidecar-hardware.md @@ -4,30 +4,31 @@ slug: "sidecar-hardware" description: "Add additional specialized hardware to your FarmBot" --- -Although FarmBot OS supports plug-and-play USB webcams, it is not possible to install additional camera drivers on FarmBot OS. FarmBot OS only supports plug-and-play cameras, and it's very important to point out that although FarmBot OS is a Linux-powered Raspberry Pi, it is not intended to be used in the same manner as a Desktop machine where end users are free to add and remove the software components running on the machine. This means that FarmBot OS is not capable of directly running specialized cameras intended for scientific or specialized use (most consumer-grade USB webcams are fine, though). FarmBot OS has a read-only filesystem and does not use the same Raspberry Pi Linux distribution that desktop Linux users are used to. +While FarmBot OS supports plug-and-play USB webcams, it is not possible to install additional camera drivers or other software onto FarmBot OS that may be required by specialized cameras. -In situations where you need to install special drivers or Python modules, we recommend adding a "sidecar" hardware module to the FarmBot. The sidecar computer would be a second Raspberry Pi (or similar) that is completely under your control and which does not run FarmBot OS. You would install Raspberry Pi OS on the sidecar and follow the directions provided by most tutorials found online. +{% +include callout.html +type="info" +content="While FarmBot OS is a Linux-powered Raspberry Pi, it is not intended to be used in the same manner as a desktop computer where end users are free to add and remove the software components. FarmBot OS has a read-only filesystem and does not use the same Raspberry Pi Linux distribution that desktop Linux users are used to." +%} + +In situations where you need to install special drivers or Python modules, we recommend using **sidecar hardware**. Sidecar hardware is a second computer, typically a Raspberry Pi (or similar), that is completely under your control and which does not run FarmBot OS. You would install [Raspberry Pi OS](https://www.raspberrypi.com/software/operating-systems/) on the sidecar and follow the directions provided by tutorials found online to run your custom software and hardware. A sidecar may also be another Arduino, a cloud-based server, or even your laptop. Once the sidecar is configured, there are a number of ways you can support interaction between the FarmBot's CPU and the sidecar: - * **[Library control](#library-control)**: If the device has a reasonably reliable internet connection, you can have the sidecar talk to FBOS via [Python](../../python/intro.md) or [FarmBotJS](../farmbot-js.md). This is the easiest option. + * **[Python library control](#python-library-control)**: If the device has a reasonably reliable internet connection, you can have the sidecar talk to FBOS via [Python](../../python/intro.md) or [FarmBotJS](../farmbot-js.md). This is the easiest option. * **[Lua UART](#lua-uart)**: You can run a serial line from the FarmBot to the sidecar and use the Lua [UART helpers](../../lua/functions/uart.md) to send messages between the devices. - * **[GPIO pin binding](#gpio-pin-binding)**: The sidecar can trigger a "pin binding" which activates a sequence on FBOS whenever the sidecar pulls a GPIO line high. + * **[GPIO pin binding](#gpio-pin-binding)**: The sidecar can trigger a [pin binding](https://software.farm.bot/docs/pin-bindings) which activates a sequence on FBOS whenever the sidecar pulls a GPIO line high. * **[Lua HTTP](#lua-http)**: You could create an HTTP server that resides on the sidecar module and [make HTTP calls from Lua code in a sequence](../../lua/functions/api.md#httpparams). - The sidecar module could then upload the photos to the FarmBot API, or you could store them on a completely different server that has higher storage limits than what the Web App provides. You could also perform image manipulation tasks directly on the sidecar. - - Other methods may be possible. - -# Examples +In the case of using a 3rd party camera system, the sidecar could be triggered to take a photo by the FarmBot, and then the sidecar could upload the photos to the FarmBot API, or you could store them on a completely different server that has higher storage limits than what the Web App provides. You could also perform image manipulation tasks directly on the sidecar. -`random()` is used here as a placeholder for the custom code you may run on your sidecar hardware. +# Python library control -## Library control +In this example your Python code could be run from another Raspberry Pi, a laptop, or even a cloud-based server and it will communicate with the FarmBot over the Internet. -### Python +_On sidecar hardware (Python):_ -_on sidecar hardware (Python):_ ```python from farmbot import Farmbot from random import randint @@ -43,52 +44,66 @@ fb.wait(seconds * 1000) # Wait for a random number of seconds fb.off(7) # Turn OFF pin 7 (LED strip) ``` -_on FarmBot:_ +_On FarmBot:_ The lighting peripheral is controlled. -See the [FarmBotPy library docs](../../python/intro.md) for additional usage instructions. +{% +include callout.html +type="info" +content="See the [FarmBotPy library docs](../../python/intro.md) for additional usage instructions." +%} + +# Lua UART + +In this example you would connect an Arduino or other UART device to a spare USB port on the FarmBot's Raspberry Pi. Make sure to use [uart.list()](../../lua/functions/uart.md#uartlist) first to check which device is your sidecar. -## Lua UART +_On sidecar hardware (Arduino):_ -_on sidecar hardware (Arduino):_ ```c void setup() { Serial.begin(115200); } void loop() { - int randNum = random(1, 11); - Serial.println(randNum); + Serial.println("Hello from the sidecar!"); delay(1000); } ``` -_on FarmBot (Lua sequence step):_ +_On FarmBot (Lua sequence step):_ + ```lua my_uart, error = uart.open("ttyUSB0", 115200) if error then - toast(inspect(error), "error") + toast(error, "error") return end if my_uart then string, error2 = my_uart.read(15000) if error2 then - toast(inspect(error2), "error") + toast(error2, "error") else - toast(inspect(string)) + toast(string) end my_uart.close() end ``` -See the [Lua UART docs](../../lua/functions/uart.md) for additional usage instructions. +{% +include callout.html +type="info" +content="See the [Lua UART docs](../../lua/functions/uart.md) for additional usage instructions." +%} + +# GPIO pin binding -## GPIO pin binding +In this example, you must connect a physical wire between an output pin on your sidecar and one of FarmBot's GPIO pins. You must then configure a [pin binding](https://software.farm.bot/docs/pin-bindings) to execute a sequence or action when triggered. + +_On sidecar hardware (Arduino):_ -_on sidecar hardware (Arduino):_ ```c int i = 0; int randNum; @@ -110,15 +125,16 @@ void loop() { } ``` -_on FarmBot:_ +_On FarmBot:_ + +The pin binding for the pin connected to the sidecar hardware is triggered and the assigned sequence or action is executed. -The pin binding for the pin connected to the sidecar hardware is triggered. +# Lua HTTP -See the [Pin Binding docs](https://software.farm.bot/docs/pin-bindings) for additional usage instructions. +In this example your Python code could be run from another Raspberry Pi or your laptop on the same network as the FarmBot. -## Lua HTTP +_On sidecar hardware (Python):_ -_on sidecar hardware (Python):_ ```python from flask import Flask import cv2 @@ -139,7 +155,7 @@ def capture_and_return_value(): # process image and return result gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) - value = int(np.mean(gray) + random()) + value = int(np.mean(gray)) return str(value) @@ -147,7 +163,7 @@ if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) ``` -_on FarmBot (Lua sequence step):_ +_On FarmBot (Lua sequence step):_ Where `192.168.0.100` is the local network IP address of the sidecar hardware. @@ -159,4 +175,8 @@ local value = tonumber(response.body) toast("processing complete. result: " .. value) ``` -See the [Lua HTTP docs](../../lua/functions/api.md) for additional usage instructions. +{% +include callout.html +type="info" +content="See the [Lua HTTP docs](../../lua/functions/api.md) for additional usage instructions." +%} diff --git a/v15/lua/functions/coordinates.md b/v15/lua/functions/coordinates.md index 059344c..9558734 100644 --- a/v15/lua/functions/coordinates.md +++ b/v15/lua/functions/coordinates.md @@ -10,7 +10,7 @@ description: "List of coordinate Lua functions in FarmBot OS" ```lua coordinate(1.0, 20, 30) --- Returns {x = 1.0, y = 20, z = 30} +-- Returns {x = 1.0, y = 20, z = 30} ``` # check_position(coordinate, tolerance) @@ -45,6 +45,91 @@ toast("Width: " .. size.y .. "mm") toast("Height: " .. size.z .. "mm") ``` +# get_generic_points({filters}) + +Returns a table of **generic points**, filtered by the optional parameters. Available filters include: `min_radius`, `max_radius`, `min_age`, `max_age`, `color`, and `at_soil_level`. + +```lua +points = get_generic_points() +toast("Total number of generic points: " .. #points) + +points = get_generic_points({at_soil_level="true"}) +toast("Points at soil level: " .. #points) + +points = get_generic_points({color="blue", min_radius=10}) +toast("Blue points with minimum radius of 10: " .. #points) + +points = get_generic_points({max_age=2}) +toast("Points younger than 2 days: " .. #points) +``` + +# get_plants({filters}) + +Returns a table of **planted plants**, filtered by the optional parameters. Available filters include: `min_radius`, `max_radius`, `min_age`, `max_age`, `plant_stage`, and `openfarm_slug`. + +{% +include callout.html +type="info" +content='By default, a `plant_stage="planted"` filter is applied.' +%} + +```lua +plants = get_plants() +toast("Total number of planted plants: " .. #plants) + +plants = get_plants({plant_stage="sprouted"}) +toast("Sprouted plants: " .. #plants) + +plants = get_plants({min_radius=10, max_age=5}) +toast("Planted plants with minimum radius of 10 and maximum age of 5: " .. #plants) + +plants = get_plants({openfarm_slug="broccoli"}) +toast("Planted Broccoli plants: " .. #plants) +``` + +# get_weeds({filters}) + +Returns a table of **active weeds**, filtered by the optional parameters. Available filters include: `min_radius`, `max_radius`, `min_age`, `max_age`, `plant_stage`, and `color`. + +{% +include callout.html +type="info" +content='By default, a `plant_stage="active"` filter is applied.' +%} + +```lua +weeds = get_weeds() +toast("Total number of active weeds: " .. #weeds) + +weeds = get_weeds({plant_stage="pending"}) +toast("Pending weeds: " .. #weeds) + +weeds = get_weeds({min_radius=10, max_age=5}) +toast("Active weeds with minimum radius of 10 and maximum age of 5: " .. #weeds) +``` + +# get_group(id|name) + +Returns a table of **current group members**, sorted by the group's **SORT BY** method. You may get a group by name or id. + +```lua +group_members = get_group("All plants") +for _, plant in pairs(group_members) do + move{x=plant.x, y=plant.y, z=0} +end +``` + +```lua +group_members = get_group(1234) +toast(#group_members) +``` + +{% +include callout.html +type="info" +content="Find a group's ID by navigating to the group in the web app and copying the number at the end of the URL." +%} + # get_seed_tray_cell(tray, cell) Calculates the **coordinates of a seed tray cell**, such as `B3`, based on the cell label and the coordinates of the center of the seed tray. See the [Pick from Seed Tray featured sequence](https://my.farm.bot/app/shared/sequence/32) for an example. @@ -121,27 +206,6 @@ title="Each iteration runs in its own execution context" content="Variables declared outside the `grid.each` iterator function will not be accessible within the function. Furthermore, variables within the iterator function will not persist across iterations or be available outside the function scope. To store and retrieve persistent variables that can be accessed both inside and outside the iterator function, use [env()](../functions/configuration.md#envkey-value--envkey)." %} -# group(id) - -Returns a table of **current group member IDs**, sorted by the group's **SORT BY** method. - -```lua -group_members = group(1234) -for i,member in ipairs(group_members) do - plant = api({ - method = "get", - url = "/api/points/" .. member - }) - move_absolute(plant.x, plant.y, 0) -end -``` - -{% -include callout.html -type="info" -content="Find a group's ID by navigating to the group in the web app and copying the number at the end of the URL." -%} - # safe_z() Returns the value of the **[SAFE HEIGHT](https://my.farm.bot/app/designer/settings?highlight=safe_height)** setting. @@ -180,12 +244,13 @@ content="This function requires at least 3 soil height measurements. When there # sort(points, method) -**Sorts** the given table of points using the chosen **sorting method**. +**Sorts** the given table of point objects using the chosen **sorting method**. ```lua -points = group(1234) +points = get_group(1234) sorted_points = sort(points, "xy_alternating") -toast("Second point ID is: " .. sorted_points[2]) +poi = sorted_points[2] +toast("Second point is at (" .. poi.x .. ", " .. poi.y .. ")") ``` The following sorting methods are available. See [point group sorting](../../other/how-it-works/point-group-sorting.md) for additional details. diff --git a/v15/lua/functions/jobs.md b/v15/lua/functions/jobs.md index 769a776..c9b1e5d 100644 --- a/v15/lua/functions/jobs.md +++ b/v15/lua/functions/jobs.md @@ -38,15 +38,6 @@ wait(2000) complete_job(job_name) ``` -# set_job_progress() - -{% -include callout.html -type="warning" -title="Deprecated" -content="This is a low-level function that has been superseded by [set_job()](#set_jobname-params)." -%} - # get_job(name) **Gets a job** by name. @@ -69,15 +60,6 @@ toast("Job progress: " .. job.percent .. "%") complete_job(job_name) ``` -# get_job_progress() - -{% -include callout.html -type="warning" -title="Deprecated" -content="This is a low-level function that has been superseded by [get_job()](#get_jobname)." -%} - # complete_job(name) **Completes a job** by name, where complete means a `percent` of `100` and a `status` of `Complete`. diff --git a/v15/other/openfarm.md b/v15/other/openfarm.md deleted file mode 100644 index c8d0466..0000000 --- a/v15/other/openfarm.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "OpenFarm" -slug: "openfarm" -description: "[OpenFarm.cc](https://openfarm.cc)" ---- - -OpenFarm is used by the FarmBot project and was created with help from members of the FarmBot team. Although FarmBot relies on OpenFarm for data, **OpenFarm is a free-standing project that operates independently from FarmBot**. - -Developer documentation is available [here](https://github.com/openfarmcc/OpenFarm/wiki).