From da939db61f8171c616b83c025f45d1ca806be68a Mon Sep 17 00:00:00 2001 From: connor rigby Date: Tue, 15 May 2018 12:23:10 -0700 Subject: [PATCH] Add ability to skip configurator --- .gitignore | 2 +- CHANGELOG.md | 1 + config/target/fwup.rpi3.conf | 387 ++++++++++++++++++ config/target/rpi3.exs | 3 + .../bootstrap/configurator/configurator.ex | 58 ++- 5 files changed, 438 insertions(+), 13 deletions(-) create mode 100644 config/target/fwup.rpi3.conf diff --git a/.gitignore b/.gitignore index e182c460..89baf86e 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ ttb_last_config /nerves/* !/nerves/host !/nerves/target -_nerves_tmp +_nerves-tmp # Secret config auth_secret_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f152ea7..5adfa781 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Remove `hostapd` * Remove a lot of custom Logger code. * Try to write the last 100 logs to a flash drive if one exists. +* Fix bugs in `send_message` block templating. # 6.4.1 * Beta updates should _always_ try to flash firmware. diff --git a/config/target/fwup.rpi3.conf b/config/target/fwup.rpi3.conf new file mode 100644 index 00000000..ee33328f --- /dev/null +++ b/config/target/fwup.rpi3.conf @@ -0,0 +1,387 @@ +# Firmware configuration file for the Raspberry Pi 3 + +require-fwup-version="0.15.0" # For the trim() call + +# +# Firmware metadata +# + +# All of these can be overriden using environment variables of the same name. +# +# Run 'fwup -m' to query values in a .fw file. +# Use 'fw_printenv' to query values on the target. +# +# These are used by Nerves libraries to introspect. +define(NERVES_FW_PRODUCT, "Nerves Firmware") +define(NERVES_FW_DESCRIPTION, "") +define(NERVES_FW_VERSION, "${NERVES_SDK_VERSION}") +define(NERVES_FW_PLATFORM, "rpi3") +define(NERVES_FW_ARCHITECTURE, "arm") +define(NERVES_FW_AUTHOR, "The Nerves Team") + +define(NERVES_FW_DEVPATH, "/dev/mmcblk0") +define(NERVES_FW_APPLICATION_PART0_DEVPATH, "/dev/mmcblk0p3") # Linux part number is 1-based +define(NERVES_FW_APPLICATION_PART0_FSTYPE, "ext4") +define(NERVES_FW_APPLICATION_PART0_TARGET, "/root") + +# Default paths if not specified via the commandline +define(ROOTFS, "${NERVES_SYSTEM}/images/rootfs.squashfs") + +# This configuration file will create an image that has an MBR and the +# following 3 partitions: +# +# +----------------------------+ +# | MBR | +# +----------------------------+ +# | Firmware configuration data| +# | (formatted as uboot env) | +# +----------------------------+ +# | p0*: Boot A (FAT32) | +# | zImage, bootcode.bin, | +# | config.txt, etc. | +# +----------------------------+ +# | p0*: Boot B (FAT32) | +# +----------------------------+ +# | p1*: Rootfs A (squashfs) | +# +----------------------------+ +# | p1*: Rootfs B (squashfs) | +# +----------------------------+ +# | p2: Application (ext4) | +# +----------------------------+ +# +# The p0/p1 partition points to whichever of configurations A or B that is +# active. +# +# The image is sized to be less than 1 GB so that it fits on nearly any SDCard +# around. If you have a larger SDCard and need more space, feel free to bump +# the partition sizes below. + +# The Raspberry Pi is incredibly picky on the partition sizes and in ways that +# I don't understand. Test changes one at a time to make sure that they boot. +# (Sizes are in 512 byte blocks) +define(UBOOT_ENV_OFFSET, 16) +define(UBOOT_ENV_COUNT, 16) # 8 KB + +define(BOOT_A_PART_OFFSET, 63) +define(BOOT_A_PART_COUNT, 38630) +define-eval(BOOT_B_PART_OFFSET, "${BOOT_A_PART_OFFSET} + ${BOOT_A_PART_COUNT}") +define(BOOT_B_PART_COUNT, ${BOOT_A_PART_COUNT}) + +# Let the rootfs have room to grow up to 128 MiB and align it to the nearest 1 +# MB boundary +define(ROOTFS_A_PART_OFFSET, 77324) +define(ROOTFS_A_PART_COUNT, 289044) +define-eval(ROOTFS_B_PART_OFFSET, "${ROOTFS_A_PART_OFFSET} + ${ROOTFS_A_PART_COUNT}") +define(ROOTFS_B_PART_COUNT, ${ROOTFS_A_PART_COUNT}) + +# Application partition. This partition can occupy all of the remaining space. +# Size it to fit the destination. +define-eval(APP_PART_OFFSET, "${ROOTFS_B_PART_OFFSET} + ${ROOTFS_B_PART_COUNT}") +define(APP_PART_COUNT, 1048576) + +# Firmware archive metadata +meta-product = ${NERVES_FW_PRODUCT} +meta-description = ${NERVES_FW_DESCRIPTION} +meta-version = ${NERVES_FW_VERSION} +meta-platform = ${NERVES_FW_PLATFORM} +meta-architecture = ${NERVES_FW_ARCHITECTURE} +meta-author = ${NERVES_FW_AUTHOR} +meta-vcs-identifier = ${NERVES_FW_VCS_IDENTIFIER} +meta-misc = ${NERVES_FW_MISC} + +# File resources are listed in the order that they are included in the .fw file +# This is important, since this is the order that they're written on a firmware +# update due to the event driven nature of the update system. +file-resource bootcode.bin { + host-path = "${NERVES_SYSTEM}/images/rpi-firmware/bootcode.bin" +} +file-resource fixup.dat { + host-path = "${NERVES_SYSTEM}/images/rpi-firmware/fixup.dat" +} +file-resource start.elf { + host-path = "${NERVES_SYSTEM}/images/rpi-firmware/start.elf" +} +file-resource config.txt { + host-path = "${NERVES_SYSTEM}/images/config.txt" +} +file-resource cmdline.txt { + host-path = "${NERVES_SYSTEM}/images/cmdline.txt" +} +file-resource zImage { + host-path = "${NERVES_SYSTEM}/images/zImage" +} +file-resource bcm2710-rpi-3-b.dtb { + host-path = "${NERVES_SYSTEM}/images/bcm2710-rpi-3-b.dtb" +} +file-resource bcm2710-rpi-cm3.dtb { + host-path = "${NERVES_SYSTEM}/images/bcm2710-rpi-cm3.dtb" +} +file-resource w1-gpio-pullup.dtbo { + host-path = "${NERVES_SYSTEM}/images/rpi-firmware/overlays/w1-gpio-pullup.dtbo" +} +file-resource pi3-miniuart-bt.dtbo { + host-path = "${NERVES_SYSTEM}/images/rpi-firmware/overlays/pi3-miniuart-bt.dtbo" +} + +file-resource rootfs.img { + host-path = ${ROOTFS} + + # Error out if the rootfs size exceeds the partition size + assert-size-lte = ${ROOTFS_A_PART_COUNT} +} + +mbr mbr-a { + partition 0 { + block-offset = ${BOOT_A_PART_OFFSET} + block-count = ${BOOT_A_PART_COUNT} + type = 0xc # FAT32 + boot = true + } + partition 1 { + block-offset = ${ROOTFS_A_PART_OFFSET} + block-count = ${ROOTFS_A_PART_COUNT} + type = 0x83 # Linux + } + partition 2 { + block-offset = ${APP_PART_OFFSET} + block-count = ${APP_PART_COUNT} + type = 0x83 # Linux + } + # partition 3 is unused +} + +mbr mbr-b { + partition 0 { + block-offset = ${BOOT_B_PART_OFFSET} + block-count = ${BOOT_B_PART_COUNT} + type = 0xc # FAT32 + boot = true + } + partition 1 { + block-offset = ${ROOTFS_B_PART_OFFSET} + block-count = ${ROOTFS_B_PART_COUNT} + type = 0x83 # Linux + } + partition 2 { + block-offset = ${APP_PART_OFFSET} + block-count = ${APP_PART_COUNT} + type = 0x83 # Linux + } + # partition 3 is unused +} + +# Location where installed firmware information is stored. +# While this is called "u-boot", u-boot isn't involved in this +# setup. It just provides a convenient key/value store format. +uboot-environment uboot-env { + block-offset = ${UBOOT_ENV_OFFSET} + block-count = ${UBOOT_ENV_COUNT} +} + +# This firmware task writes everything to the destination media +task complete { + # Only match if not mounted + require-unmounted-destination = true + + on-init { + mbr_write(mbr-a) + + uboot_clearenv(uboot-env) + uboot_setenv(uboot-env, "nerves_fw_active", "a") + uboot_setenv(uboot-env, "nerves_fw_devpath", ${NERVES_FW_DEVPATH}) + uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH}) + uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE}) + uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET}) + uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT}) + uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION}) + uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION}) + uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM}) + uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE}) + uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR}) + uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER}) + uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC}) + uboot_setenv(uboot-env, "farmbot_email", ${FARMBOT_EMAIL}) + uboot_setenv(uboot-env, "farmbot_password", ${FARMBOT_PASSWORD}) + uboot_setenv(uboot-env, "farmbot_server", ${FARMBOT_SERVER}) + uboot_setenv(uboot-env, "farmbot_auto_configure", ${FARMBOT_AUTO_CONFIGURE}) + uboot_setenv(uboot-env, "farmbot_network_iface", ${FARMBOT_NETWORK_IFACE}) + uboot_setenv(uboot-env, "farmbot_network_ssid", ${FARMBOT_NETWORK_SSID}) + uboot_setenv(uboot-env, "farmbot_network_psk", ${FARMBOT_NETWORK_PSK}) + + fat_mkfs(${BOOT_A_PART_OFFSET}, ${BOOT_A_PART_COUNT}) + fat_setlabel(${BOOT_A_PART_OFFSET}, "BOOT-A") + fat_mkdir(${BOOT_A_PART_OFFSET}, "overlays") + } + + on-resource config.txt { fat_write(${BOOT_A_PART_OFFSET}, "config.txt") } + on-resource cmdline.txt { fat_write(${BOOT_A_PART_OFFSET}, "cmdline.txt") } + on-resource bootcode.bin { fat_write(${BOOT_A_PART_OFFSET}, "bootcode.bin") } + on-resource start.elf { fat_write(${BOOT_A_PART_OFFSET}, "start.elf") } + on-resource fixup.dat { fat_write(${BOOT_A_PART_OFFSET}, "fixup.dat") } + on-resource zImage { fat_write(${BOOT_A_PART_OFFSET}, "zImage") } + on-resource bcm2710-rpi-3-b.dtb { fat_write(${BOOT_A_PART_OFFSET}, "bcm2710-rpi-3-b.dtb") } + on-resource bcm2710-rpi-cm3.dtb { fat_write(${BOOT_A_PART_OFFSET}, "bcm2710-rpi-cm3.dtb") } + on-resource w1-gpio-pullup.dtbo { fat_write(${BOOT_A_PART_OFFSET}, "overlays/w1-gpio-pullup.dtbo") } + on-resource pi3-miniuart-bt.dtbo { fat_write(${BOOT_A_PART_OFFSET}, "overlays/pi3-miniuart-bt.dtbo") } + + on-resource rootfs.img { + # write to the first rootfs partition + raw_write(${ROOTFS_A_PART_OFFSET}) + } + + on-finish { + # Clear out any old data in the B partition that might be mistaken for + # a file system. This is mostly to avoid confusion in humans when + # reprogramming SDCards with unknown contents. + raw_memset(${BOOT_B_PART_OFFSET}, 256, 0xff) + raw_memset(${ROOTFS_B_PART_OFFSET}, 256, 0xff) + + # Invalidate the application data partition so that it is guaranteed to + # trigger the corrupt filesystem detection code on first boot and get + # formatted. If this isn't done and an old SDCard is reused, the + # application data could be in a weird state. + raw_memset(${APP_PART_OFFSET}, 256, 0xff) + } +} + +task upgrade.a { + # This task upgrades the A partition + require-partition-offset(1, ${ROOTFS_B_PART_OFFSET}) + + # Verify the expected platform/architecture + require-uboot-variable(uboot-env, "b.nerves_fw_platform", "${NERVES_FW_PLATFORM}") + require-uboot-variable(uboot-env, "b.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}") + + on-init { + info("Upgrading partition A") + + # Clear some firmware information just in case this update gets + # interrupted midway. If this partition was bootable, it's not going to + # be soon. + uboot_unsetenv(uboot-env, "a.nerves_fw_version") + uboot_unsetenv(uboot-env, "a.nerves_fw_platform") + uboot_unsetenv(uboot-env, "a.nerves_fw_architecture") + + # Reset the previous contents of the A boot partition + fat_mkfs(${BOOT_A_PART_OFFSET}, ${BOOT_A_PART_COUNT}) + fat_setlabel(${BOOT_A_PART_OFFSET}, "BOOT-A") + fat_mkdir(${BOOT_A_PART_OFFSET}, "overlays") + + # Indicate that the entire partition can be cleared + trim(${ROOTFS_A_PART_OFFSET}, ${ROOTFS_A_PART_COUNT}) + } + + # Write the new boot partition files and rootfs. The MBR still points + # to the B partition, so an error or power failure during this part + # won't hurt anything. + on-resource config.txt { fat_write(${BOOT_A_PART_OFFSET}, "config.txt") } + on-resource cmdline.txt { fat_write(${BOOT_A_PART_OFFSET}, "cmdline.txt") } + on-resource bootcode.bin { fat_write(${BOOT_A_PART_OFFSET}, "bootcode.bin") } + on-resource start.elf { fat_write(${BOOT_A_PART_OFFSET}, "start.elf") } + on-resource fixup.dat { fat_write(${BOOT_A_PART_OFFSET}, "fixup.dat") } + on-resource zImage { fat_write(${BOOT_A_PART_OFFSET}, "zImage") } + on-resource bcm2710-rpi-3-b.dtb { fat_write(${BOOT_A_PART_OFFSET}, "bcm2710-rpi-3-b.dtb") } + on-resource bcm2710-rpi-cm3.dtb { fat_write(${BOOT_A_PART_OFFSET}, "bcm2710-rpi-cm3.dtb") } + on-resource w1-gpio-pullup.dtbo { fat_write(${BOOT_A_PART_OFFSET}, "overlays/w1-gpio-pullup.dtbo") } + on-resource pi3-miniuart-bt.dtbo { fat_write(${BOOT_A_PART_OFFSET}, "overlays/pi3-miniuart-bt.dtbo") } + on-resource rootfs.img { raw_write(${ROOTFS_A_PART_OFFSET}) } + + on-finish { + # Update firmware metadata + uboot_setenv(uboot-env, "a.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH}) + uboot_setenv(uboot-env, "a.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE}) + uboot_setenv(uboot-env, "a.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET}) + uboot_setenv(uboot-env, "a.nerves_fw_product", ${NERVES_FW_PRODUCT}) + uboot_setenv(uboot-env, "a.nerves_fw_description", ${NERVES_FW_DESCRIPTION}) + uboot_setenv(uboot-env, "a.nerves_fw_version", ${NERVES_FW_VERSION}) + uboot_setenv(uboot-env, "a.nerves_fw_platform", ${NERVES_FW_PLATFORM}) + uboot_setenv(uboot-env, "a.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE}) + uboot_setenv(uboot-env, "a.nerves_fw_author", ${NERVES_FW_AUTHOR}) + uboot_setenv(uboot-env, "a.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER}) + uboot_setenv(uboot-env, "a.nerves_fw_misc", ${NERVES_FW_MISC}) + + # Switch over to boot the new firmware + uboot_setenv(uboot-env, "nerves_fw_active", "a") + mbr_write(mbr-a) + } + + on-error { + } +} + +task upgrade.b { + # This task upgrades the B partition + require-partition-offset(1, ${ROOTFS_A_PART_OFFSET}) + + # Verify the expected platform/architecture + require-uboot-variable(uboot-env, "a.nerves_fw_platform", "${NERVES_FW_PLATFORM}") + require-uboot-variable(uboot-env, "a.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}") + + on-init { + info("Upgrading partition B") + + # Clear some firmware information just in case this update gets + # interrupted midway. + uboot_unsetenv(uboot-env, "b.nerves_fw_version") + uboot_unsetenv(uboot-env, "b.nerves_fw_platform") + uboot_unsetenv(uboot-env, "b.nerves_fw_architecture") + + # Reset the previous contents of the B boot partition + fat_mkfs(${BOOT_B_PART_OFFSET}, ${BOOT_B_PART_COUNT}) + fat_setlabel(${BOOT_B_PART_OFFSET}, "BOOT-B") + fat_mkdir(${BOOT_B_PART_OFFSET}, "overlays") + + trim(${ROOTFS_B_PART_OFFSET}, ${ROOTFS_B_PART_COUNT}) + } + + # Write the new boot partition files and rootfs. The MBR still points + # to the A partition, so an error or power failure during this part + # won't hurt anything. + on-resource config.txt { fat_write(${BOOT_B_PART_OFFSET}, "config.txt") } + on-resource cmdline.txt { fat_write(${BOOT_B_PART_OFFSET}, "cmdline.txt") } + on-resource bootcode.bin { fat_write(${BOOT_B_PART_OFFSET}, "bootcode.bin") } + on-resource start.elf { fat_write(${BOOT_B_PART_OFFSET}, "start.elf") } + on-resource fixup.dat { fat_write(${BOOT_B_PART_OFFSET}, "fixup.dat") } + on-resource zImage { fat_write(${BOOT_B_PART_OFFSET}, "zImage") } + on-resource bcm2710-rpi-3-b.dtb { fat_write(${BOOT_B_PART_OFFSET}, "bcm2710-rpi-3-b.dtb") } + on-resource bcm2710-rpi-cm3.dtb { fat_write(${BOOT_B_PART_OFFSET}, "bcm2710-rpi-cm3.dtb") } + on-resource w1-gpio-pullup.dtbo { fat_write(${BOOT_B_PART_OFFSET}, "overlays/w1-gpio-pullup.dtbo") } + on-resource pi3-miniuart-bt.dtbo { fat_write(${BOOT_B_PART_OFFSET}, "overlays/pi3-miniuart-bt.dtbo") } + on-resource rootfs.img { raw_write(${ROOTFS_B_PART_OFFSET}) } + + on-finish { + # Update firmware metadata + uboot_setenv(uboot-env, "b.nerves_fw_application_part0_devpath", ${NERVES_FW_APPLICATION_PART0_DEVPATH}) + uboot_setenv(uboot-env, "b.nerves_fw_application_part0_fstype", ${NERVES_FW_APPLICATION_PART0_FSTYPE}) + uboot_setenv(uboot-env, "b.nerves_fw_application_part0_target", ${NERVES_FW_APPLICATION_PART0_TARGET}) + uboot_setenv(uboot-env, "b.nerves_fw_product", ${NERVES_FW_PRODUCT}) + uboot_setenv(uboot-env, "b.nerves_fw_description", ${NERVES_FW_DESCRIPTION}) + uboot_setenv(uboot-env, "b.nerves_fw_version", ${NERVES_FW_VERSION}) + uboot_setenv(uboot-env, "b.nerves_fw_platform", ${NERVES_FW_PLATFORM}) + uboot_setenv(uboot-env, "b.nerves_fw_architecture", ${NERVES_FW_ARCHITECTURE}) + uboot_setenv(uboot-env, "b.nerves_fw_author", ${NERVES_FW_AUTHOR}) + uboot_setenv(uboot-env, "b.nerves_fw_vcs_identifier", ${NERVES_FW_VCS_IDENTIFIER}) + uboot_setenv(uboot-env, "b.nerves_fw_misc", ${NERVES_FW_MISC}) + + # Switch over to boot the new firmware + uboot_setenv(uboot-env, "nerves_fw_active", "b") + mbr_write(mbr-b) + } + + on-error { + } +} + +task upgrade.unexpected { + require-uboot-variable(uboot-env, "a.nerves_fw_platform", "${NERVES_FW_PLATFORM}") + require-uboot-variable(uboot-env, "a.nerves_fw_architecture", "${NERVES_FW_ARCHITECTURE}") + on-init { + error("Please check the media being upgraded. It doesn't look like either the A or B partitions are active.") + } +} + +task upgrade.wrongplatform { + on-init { + error("Expecting platform=${NERVES_FW_PLATFORM} and architecture=${NERVES_FW_ARCHITECTURE}") + } +} diff --git a/config/target/rpi3.exs b/config/target/rpi3.exs index 937c7b95..892c88f7 100644 --- a/config/target/rpi3.exs +++ b/config/target/rpi3.exs @@ -6,3 +6,6 @@ config :farmbot, :gpio, status_led_off: true config :farmbot, :captive_portal_address, "192.168.24.1" config :farmbot, kernel_modules: ["snd-bcm2835"] + +config :nerves, :firmware, + fwup_conf: "config/target/fwup.rpi3.conf" diff --git a/platform/target/bootstrap/configurator/configurator.ex b/platform/target/bootstrap/configurator/configurator.ex index 55b2df58..b2dbdbce 100644 --- a/platform/target/bootstrap/configurator/configurator.ex +++ b/platform/target/bootstrap/configurator/configurator.ex @@ -44,19 +44,11 @@ defmodule Farmbot.Target.Bootstrap.Configurator do def init(_) do first_boot? = ConfigStorage.get_config_value(:bool, "settings", "first_boot") - if first_boot? do - Logger.info(3, "Building new configuration.") - import Supervisor.Spec - :ets.new(:session, [:named_table, :public, read_concurrency: true]) - Farmbot.System.GPIO.Leds.led_status_err() - ConfigStorage.destroy_all_network_configs() - children = [ - worker(Configurator.CaptivePortal, []), - {Plug.Adapters.Cowboy, scheme: :http, plug: Configurator.Router, options: [port: 80, acceptors: 1]} - ] + autoconfigure? = Nerves.Runtime.KV.get("farmbot_auto_configure") - opts = [strategy: :one_for_one] - Supervisor.init(children, opts) + + if first_boot? do + maybe_configurate(autoconfigure?) else :ignore end @@ -66,4 +58,46 @@ defmodule Farmbot.Target.Bootstrap.Configurator do Supervisor.stop(supervisor, :normal) status end + + defp maybe_configurate(nil) do + Logger.info(3, "Building new configuration.") + import Supervisor.Spec + :ets.new(:session, [:named_table, :public, read_concurrency: true]) + Farmbot.System.GPIO.Leds.led_status_err() + ConfigStorage.destroy_all_network_configs() + children = [ + worker(Configurator.CaptivePortal, []), + {Plug.Adapters.Cowboy, scheme: :http, plug: Configurator.Router, options: [port: 80, acceptors: 1]} + ] + + opts = [strategy: :one_for_one] + Supervisor.init(children, opts) + end + + defp maybe_configurate(_) do + ifname = Nerves.Runtime.KV.get("farmbot_network_iface") + ssid = Nerves.Runtime.KV.get("farmbot_network_ssid") + psk = Nerves.Runtime.KV.get("farmbot_network_psk") + email = Nerves.Runtime.KV.get("farmbot_email") + server = Nerves.Runtime.KV.get("farmbot_server") + password = Nerves.Runtime.KV.get("farmbot_password") + ConfigStorage.input_network_config!(%{ + name: ifname, + ssid: ssid, + security: "WPA-PSK", psk: psk, + type: if(ssid, do: "wireless", else: "wired"), + domain: nil, + name_servers: nil, + ipv4_method: "dhcp", + ipv4_address: nil, + ipv4_gateway: nil, + ipv4_subnet_mask: nil + }) + + ConfigStorage.update_config_value(:string, "authorization", "email", email) + ConfigStorage.update_config_value(:string, "authorization", "password", password) + ConfigStorage.update_config_value(:string, "authorization", "server", server) + ConfigStorage.update_config_value(:string, "authorization", "token", nil) + :ignore + end end