├── test ├── test_helper.exs └── scanner_test.exs ├── lib ├── scanner.ex └── scanner │ ├── application.ex │ ├── upc_database_api.ex │ ├── wunderlist_api.ex │ └── coordinator.ex ├── scanner.jpg ├── .formatter.exs ├── .build_config.example ├── .gitignore ├── rel ├── vm.args └── config.exs ├── README.md ├── config └── config.exs ├── mix.exs ├── mix.lock.host └── mix.lock.rpi0 /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /lib/scanner.ex: -------------------------------------------------------------------------------- 1 | defmodule Scanner do 2 | end 3 | -------------------------------------------------------------------------------- /scanner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Carrigan/wunderscan/HEAD/scanner.jpg -------------------------------------------------------------------------------- /.formatter.exs: -------------------------------------------------------------------------------- 1 | # Used by "mix format" 2 | [ 3 | inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"] 4 | ] 5 | -------------------------------------------------------------------------------- /test/scanner_test.exs: -------------------------------------------------------------------------------- 1 | defmodule ScannerTest do 2 | use ExUnit.Case 3 | doctest Scanner 4 | 5 | test "the truth" do 6 | assert 1 + 1 == 2 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /.build_config.example: -------------------------------------------------------------------------------- 1 | export MIX_TARGET=rpi0 2 | export NERVES_NETWORK_SSID=your_wifi_ssid 3 | export NERVES_NETWORK_PSK=your_wifi_password 4 | export WUNDERLIST_ACCESS_KEY=your_key 5 | export WUNDERLIST_CLIENT_ID=your_client_id 6 | export UPCDATABASE_ACCESS_KEY=your_key 7 | -------------------------------------------------------------------------------- /lib/scanner/application.ex: -------------------------------------------------------------------------------- 1 | defmodule Scanner.Application do 2 | use Application 3 | 4 | def start(_type, _args) do 5 | import Supervisor.Spec, warn: false 6 | 7 | children = [Scanner.Coordinator] 8 | opts = [strategy: :one_for_one, name: Scanner.Supervisor] 9 | Supervisor.start_link(children, opts) 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build/ 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover/ 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps/ 9 | 10 | # Where 3rd-party dependencies like ExDoc output generated docs. 11 | /doc/ 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Leave out the actual build config 20 | .build_config 21 | -------------------------------------------------------------------------------- /lib/scanner/upc_database_api.ex: -------------------------------------------------------------------------------- 1 | defmodule Scanner.UpcDatabaseApi do 2 | @required_fields ~w(title description) 3 | 4 | def lookup(upc) do 5 | HTTPoison.get(uri("/product/0#{upc}"), [], hackney: [:insecure]) |> process_response() 6 | end 7 | 8 | def process_response({:ok, %HTTPoison.Response{body: body}}) do 9 | Poison.decode!(body) 10 | |> build_ok() 11 | end 12 | 13 | def process_response(error, _), do: error 14 | 15 | defp build_ok(output) do 16 | {:ok, output} 17 | end 18 | 19 | defp uri(suffix) do 20 | "https://api.upcdatabase.org" <> suffix <> access_key() 21 | end 22 | 23 | defp access_key() do 24 | "/#{Application.get_env(:scanner, :upcdatabase_access_key)}" 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /rel/vm.args: -------------------------------------------------------------------------------- 1 | ## Add custom options here 2 | 3 | ## Distributed Erlang Options 4 | ## The cookie needs to be configured prior to vm boot for 5 | ## for read only filesystem. 6 | 7 | # -name scanner@0.0.0.0 8 | -setcookie fMg2PaNPDiPGtAGSpn5/LGagQtfbfdFjJD3nEgo3R+izK3e++Hu5v8lBfyL9ThOx 9 | 10 | ## Use Ctrl-C to interrupt the current shell rather than invoking the emulator's 11 | ## break handler and possibly exiting the VM. 12 | +Bc 13 | 14 | ## Save the shell history between reboots 15 | ## See http://erlang.org/doc/man/kernel_app.html for additional options 16 | -kernel shell_history enabled 17 | 18 | ## Start the Elixir shell 19 | 20 | -noshell 21 | -user Elixir.IEx.CLI 22 | 23 | ## Enable colors in the shell 24 | -elixir ansi_enabled true 25 | 26 | ## Options added after -extra are interpreted as plain arguments and 27 | ## can be retrieved using :init.get_plain_arguments(). 28 | -extra --no-halt 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wunderscan 2 | 3 | ![](scanner.jpg) 4 | 5 | This repository is for a Wunderlist-connected scanner for adding spices or snacks that you have run out of to your shopping list. 6 | 7 | ## Building this Project 8 | 9 | 1. Copy the `.build_config.example` file as `.build_config` and replace the variables with your keys and info. 10 | 1. Run the `mix firmware` command to build the project. 11 | 12 | ## Using SSH With Nerves 13 | 14 | 1. SSH into the Pi using `ssh -p 8989`. 15 | 1. In the Erlang terminal, run the command `'Elixir.IEx':start().` to use Elixir's IEx. 16 | 17 | ## Official Nerves Resources 18 | 19 | If you get stuck on any Nerves-related issues, the following resources are available: 20 | 21 | * Official docs: https://hexdocs.pm/nerves/getting-started.html 22 | * Official website: http://www.nerves-project.org/ 23 | * Discussion Slack elixir-lang #nerves ([Invite](https://elixir-slackin.herokuapp.com/)) 24 | * Source: https://github.com/nerves-project/nerves 25 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | use Mix.Config 2 | 3 | config :logger, backends: [RingLogger] 4 | config :logger, RingLogger, max_size: 200 5 | 6 | config :shoehorn, 7 | init: [:nerves_runtime, :nerves_init_gadget], 8 | app: Mix.Project.config()[:app] 9 | 10 | key_mgmt = System.get_env("NERVES_NETWORK_KEY_MGMT") || "WPA-PSK" 11 | 12 | config :nerves_network, :default, wlan0: [ 13 | ssid: System.get_env("NERVES_NETWORK_SSID"), 14 | psk: System.get_env("NERVES_NETWORK_PSK"), 15 | key_mgmt: String.to_atom(key_mgmt) 16 | ] 17 | 18 | config :nerves_init_gadget, 19 | ifname: "wlan0", 20 | address_method: :dhcp, 21 | mdns_domain: "nerves.local", 22 | node_name: nil, 23 | node_host: :mdns_domain 24 | 25 | config :scanner, 26 | wunderlist_access_key: System.get_env("WUNDERLIST_ACCESS_KEY"), 27 | wunderlist_client_id: System.get_env("WUNDERLIST_CLIENT_ID"), 28 | upcdatabase_access_key: System.get_env("UPCDATABASE_ACCESS_KEY"), 29 | list_name: "Scanned Groceries" 30 | 31 | config :nerves_firmware_ssh, 32 | authorized_keys: [File.read!(Path.join(System.user_home!, ".ssh/id_rsa.pub"))] 33 | -------------------------------------------------------------------------------- /lib/scanner/wunderlist_api.ex: -------------------------------------------------------------------------------- 1 | defmodule Scanner.WunderlistApi do 2 | require Logger 3 | 4 | def find_list_id(title) do 5 | uri("/lists") 6 | |> HTTPoison.get(auth_headers(), hackney: [:insecure]) 7 | |> process_response(title) 8 | end 9 | 10 | def create_todo(list_id, title) do 11 | todo_body = Poison.encode!(%{ "list_id" => list_id, "title" => title }) 12 | 13 | response = uri("/tasks") 14 | |> HTTPoison.post(todo_body, auth_headers() ++ ["Content-Type": "application/json"], hackney: [:insecure]) 15 | end 16 | 17 | def process_response({:ok, %HTTPoison.Response{body: body}}, title) do 18 | Poison.decode!(body) 19 | |> Enum.find(%{}, fn list_item -> Map.get(list_item, "title") == title end) 20 | |> Map.fetch("id") 21 | end 22 | 23 | def process_response(error, _), do: error 24 | 25 | defp uri(suffix) do 26 | "https://a.wunderlist.com/api/v1" <> suffix 27 | end 28 | 29 | defp auth_headers() do 30 | [ 31 | "X-Access-Token": Application.get_env(:scanner, :wunderlist_access_key), 32 | "X-Client-Id": Application.get_env(:scanner, :wunderlist_client_id) 33 | ] 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /rel/config.exs: -------------------------------------------------------------------------------- 1 | use Mix.Releases.Config, 2 | # This sets the default release built by `mix release` 3 | default_release: :default, 4 | # This sets the default environment used by `mix release` 5 | default_environment: :dev 6 | 7 | # For a full list of config options for both releases 8 | # and environments, visit https://hexdocs.pm/distillery/configuration.html 9 | 10 | 11 | # You may define one or more environments in this file, 12 | # an environment's settings will override those of a release 13 | # when building in that environment, this combination of release 14 | # and environment configuration is called a profile 15 | 16 | environment :dev do 17 | set cookie: :"opiL^k!4ibEk|&FpU8M_Dn.fSQ2=5gDTj0X>HP.ND=qSVyic8x>u;zi[qgJU|:IZ" 18 | end 19 | 20 | environment :prod do 21 | set cookie: :"opiL^k!4ibEk|&FpU8M_Dn.fSQ2=5gDTj0X>HP.ND=qSVyic8x>u;zi[qgJU|:IZ" 22 | end 23 | 24 | # You may define one or more releases in this file. 25 | # If you have not set a default release, or selected one 26 | # when running `mix release`, the first release in the file 27 | # will be used by default 28 | 29 | release :scanner do 30 | set version: current_version(:scanner) 31 | plugin Shoehorn 32 | if System.get_env("NERVES_SYSTEM") do 33 | set dev_mode: false 34 | set include_src: false 35 | set include_erts: System.get_env("ERL_LIB_DIR") 36 | set include_system_libs: System.get_env("ERL_SYSTEM_LIB_DIR") 37 | set vm_args: "rel/vm.args" 38 | end 39 | end 40 | 41 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Scanner.MixProject do 2 | use Mix.Project 3 | 4 | @target System.get_env("MIX_TARGET") || "host" 5 | 6 | def project do 7 | [ 8 | app: :scanner, 9 | version: "0.1.0", 10 | elixir: "~> 1.4", 11 | target: @target, 12 | archives: [nerves_bootstrap: "~> 0.8"], 13 | deps_path: "deps/#{@target}", 14 | build_path: "_build/#{@target}", 15 | lockfile: "mix.lock.#{@target}", 16 | build_embedded: Mix.env == :prod, 17 | start_permanent: Mix.env == :prod, 18 | aliases: ["loadconfig": [&bootstrap/1]], 19 | deps: deps() 20 | ] 21 | end 22 | 23 | # Starting nerves_bootstrap adds the required aliases to Mix.Project.config() 24 | # Aliases are only added if MIX_TARGET is set. 25 | def bootstrap(args) do 26 | Application.start(:nerves_bootstrap) 27 | Mix.Task.run("loadconfig", args) 28 | end 29 | 30 | # Run "mix help compile.app" to learn about applications. 31 | def application, do: application(@target) 32 | 33 | # Specify target specific application configurations 34 | # It is common that the application start function will start and supervise 35 | # applications which could cause the host to fail. Because of this, we only 36 | # invoke Scanner.start/2 when running on a target. 37 | def application("host") do 38 | [extra_applications: [:logger]] 39 | end 40 | 41 | def application(_target) do 42 | [mod: {Scanner.Application, []}, extra_applications: [:logger]] 43 | end 44 | 45 | # Run "mix help deps" to learn about dependencies. 46 | defp deps do 47 | [ 48 | {:nerves, "~> 0.9", runtime: false}, 49 | {:nerves_uart, "~> 1.2"}, 50 | {:nerves_init_gadget, "~> 0.2"}, 51 | {:ring_logger, "~> 0.4"}, 52 | {:httpoison, "~> 1.0"}, 53 | {:poison, "~> 3.1"} 54 | ] ++ deps(@target) 55 | end 56 | 57 | # Specify target specific dependencies 58 | defp deps("host"), do: [] 59 | 60 | defp deps(target) do 61 | [ 62 | {:shoehorn, "~> 0.2"}, 63 | {:nerves_runtime, "~> 0.4"}, 64 | {:nerves_network, "~> 0.3"}, 65 | {:nerves_firmware_ssh, "~> 0.2"} 66 | ] ++ system(target) 67 | end 68 | 69 | defp system("rpi0"), do: [{:nerves_system_rpi0, ">= 0.0.0", runtime: false}] 70 | defp system(target), do: Mix.raise "Unknown MIX_TARGET: #{target}" 71 | 72 | end 73 | -------------------------------------------------------------------------------- /lib/scanner/coordinator.ex: -------------------------------------------------------------------------------- 1 | defmodule Scanner.Coordinator do 2 | use GenServer 3 | require Logger 4 | 5 | def start_link(opts) do 6 | GenServer.start_link(__MODULE__, "ttyAMA0", opts) 7 | end 8 | 9 | def init(port) do 10 | #Start the NERVES port 11 | begin_serial(port) 12 | 13 | # Start httpoison 14 | HTTPoison.start() 15 | 16 | # Start the polling 17 | send(self(), :ethernet_check) 18 | 19 | {:ok, %{ id: nil }} 20 | end 21 | 22 | def handle_info(:ethernet_check, _) do 23 | case Nerves.Network.status("wlan0") do 24 | %{is_up: true} -> { :noreply, %{ id: retrieve_id() }} 25 | _ -> 26 | :timer.sleep(2000) 27 | send(self(), :ethernet_check) 28 | { :noreply, %{ id: nil } } 29 | end 30 | end 31 | 32 | 33 | def handle_info(_, %{id: nil} = state) do 34 | Logger.error "No ID in state... doing nothing," 35 | {:noreply, state} 36 | end 37 | 38 | def handle_info({:nerves_uart, _pid, barcode}, %{id: id}) do 39 | # Check the barcode 40 | todo_title = case Scanner.UpcDatabaseApi.lookup(barcode) do 41 | {:ok, product_map} -> get_best_name(product_map, barcode) 42 | _ -> "Barcode error: #{barcode}" 43 | end 44 | 45 | # Post the item 46 | Scanner.WunderlistApi.create_todo(id, todo_title) 47 | Logger.info "Got info: #{barcode}. Posted item: #{todo_title}" 48 | 49 | # Keep the state constant 50 | {:noreply, %{ id: id }} 51 | end 52 | 53 | defp get_best_name(product_map, barcode) do 54 | try_item_title(product_map) 55 | |> try_item_description() 56 | |> fallback_to_barcode(barcode) 57 | end 58 | 59 | defp try_item_title(product_map) do 60 | case Map.fetch(product_map, "title") do 61 | {:ok, ""} -> {:error, product_map} 62 | {:ok, title} -> {:ok, title} 63 | _ -> {:error, product_map} 64 | end 65 | end 66 | 67 | defp try_item_description({:error, product_map}) do 68 | case Map.fetch(product_map, :description) do 69 | {:ok, ""} -> {:error, product_map} 70 | {:ok, description} -> {:ok, description} 71 | _ -> {:error, product_map} 72 | end 73 | end 74 | 75 | defp try_item_description(passthrough), do: passthrough 76 | 77 | defp fallback_to_barcode({:ok, title}, _), do: title 78 | defp fallback_to_barcode(_, barcode), do: "Barcode error: #{barcode}" 79 | 80 | defp begin_serial(port) do 81 | {:ok, pid} = Nerves.UART.start_link 82 | Nerves.UART.open(pid, port, speed: 9600, active: true) 83 | Nerves.UART.configure(pid, framing: {Nerves.UART.Framing.Line, separator: "\r\n"}) 84 | 85 | pid 86 | end 87 | 88 | defp retrieve_id() do 89 | response = Application.get_env(:scanner, :list_name) 90 | |> Scanner.WunderlistApi.find_list_id() 91 | 92 | case response do 93 | {:ok, id} -> id 94 | {:error, error} -> 95 | Logger.error error.reason 96 | nil 97 | end 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /mix.lock.host: -------------------------------------------------------------------------------- 1 | %{ 2 | "certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, 3 | "distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [:mix], [], "hexpm"}, 4 | "dns": {:hex, :dns, "2.0.0", "701cc7bde399565b7aa16813cca7b7bb079c80b3bd846363b581ba45a04d8262", [:mix], [{:socket, "~> 0.3.13", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"}, 5 | "elixir_make": {:hex, :elixir_make, "0.4.1", "6628b86053190a80b9072382bb9756a6c78624f208ec0ff22cb94c8977d80060", [:mix], [], "hexpm"}, 6 | "hackney": {:hex, :hackney, "1.12.1", "8bf2d0e11e722e533903fe126e14d6e7e94d9b7983ced595b75f532e04b7fdc7", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, 7 | "httpoison": {:hex, :httpoison, "1.1.0", "497949fb62924432f64a45269d20e6f61ecf35084ffa270917afcdb7cd4d8061", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, 8 | "idna": {:hex, :idna, "5.1.1", "cbc3b2fa1645113267cc59c760bafa64b2ea0334635ef06dbac8801e42f7279c", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, 9 | "mdns": {:hex, :mdns, "1.0.1", "c0e490f7c90ee6b546284c942ebb1c239375fb5f788e765d22ea8ff848cfe842", [:mix], [{:dns, "~> 2.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"}, 10 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, 11 | "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, 12 | "nerves": {:hex, :nerves, "0.11.0", "631693062f2fdad92b2f9d34ac7c230bbda985276b5cd99e6beff7c1a0545326", [:mix], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"}, 13 | "nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.2", "2cdf126b5b264ec11c31f58b7f9933445eb065348a0b33c6762f08b1f46e87a9", [:mix], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"}, 14 | "nerves_init_gadget": {:hex, :nerves_init_gadget, "0.3.0", "4c8fdd6af9f9ad82763d7e93ab1a3f380f64d4b2804cf70acad907261b7b16be", [:mix], [{:mdns, "~> 1.0", [hex: :mdns, repo: "hexpm", optional: false]}, {:nerves_firmware_ssh, "~> 0.2", [hex: :nerves_firmware_ssh, repo: "hexpm", optional: false]}, {:nerves_network, "~> 0.3", [hex: :nerves_network, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.3", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:ring_logger, "~> 0.4", [hex: :ring_logger, repo: "hexpm", optional: false]}], "hexpm"}, 15 | "nerves_network": {:hex, :nerves_network, "0.3.6", "c95779283ace071e9d12882d6a80e31edc8c476012adc61aba2ff6c306ef97b3", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nerves_network_interface, "~> 0.4.0", [hex: :nerves_network_interface, repo: "hexpm", optional: false]}, {:nerves_wpa_supplicant, "~> 0.3.0", [hex: :nerves_wpa_supplicant, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.4", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"}, 16 | "nerves_network_interface": {:hex, :nerves_network_interface, "0.4.4", "200b1a84bc1a7fdeaf3a1e0e2d4e9b33e240b034e73f39372768d43f8690bae0", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, 17 | "nerves_runtime": {:hex, :nerves_runtime, "0.6.0", "b7336e34e65bb6c3792525587b639c4027773496a48c2eba93a78b4e7166a7ed", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"}, 18 | "nerves_uart": {:hex, :nerves_uart, "1.2.0", "195424116b925cd3bf9d666be036c2a80655e6ca0f8d447e277667a60005c50e", [:mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, 19 | "nerves_wpa_supplicant": {:hex, :nerves_wpa_supplicant, "0.3.2", "19dc7e1248336e7f542b11b2b857ceb5b088d3eb41a6ca75b7b76628dcf67aad", [:make, :mix], [{:elixir_make, "~> 0.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, 20 | "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"}, 21 | "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, 22 | "ring_logger": {:hex, :ring_logger, "0.4.0", "d58b2d9be6350d291fde90c734dcd56cb50b9be7cae4868163088db84a499e92", [:mix], [], "hexpm"}, 23 | "socket": {:hex, :socket, "0.3.13", "98a2ab20ce17f95fb512c5cadddba32b57273e0d2dba2d2e5f976c5969d0c632", [:mix], [], "hexpm"}, 24 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, 25 | "system_registry": {:hex, :system_registry, "0.8.0", "09240347628b001433d18279a2759ef7237ba7361239890d8c599cca9a2fbbc2", [:mix], [], "hexpm"}, 26 | "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}, 27 | } 28 | -------------------------------------------------------------------------------- /mix.lock.rpi0: -------------------------------------------------------------------------------- 1 | %{ 2 | "certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, 3 | "distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [:mix], [], "hexpm"}, 4 | "dns": {:hex, :dns, "2.0.0", "701cc7bde399565b7aa16813cca7b7bb079c80b3bd846363b581ba45a04d8262", [:mix], [{:socket, "~> 0.3.13", [hex: :socket, repo: "hexpm", optional: false]}], "hexpm"}, 5 | "elixir_make": {:hex, :elixir_make, "0.4.1", "6628b86053190a80b9072382bb9756a6c78624f208ec0ff22cb94c8977d80060", [:mix], [], "hexpm"}, 6 | "hackney": {:hex, :hackney, "1.12.1", "8bf2d0e11e722e533903fe126e14d6e7e94d9b7983ced595b75f532e04b7fdc7", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.1", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, 7 | "httpoison": {:hex, :httpoison, "1.1.0", "497949fb62924432f64a45269d20e6f61ecf35084ffa270917afcdb7cd4d8061", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, 8 | "idna": {:hex, :idna, "5.1.1", "cbc3b2fa1645113267cc59c760bafa64b2ea0334635ef06dbac8801e42f7279c", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, 9 | "mdns": {:hex, :mdns, "1.0.1", "c0e490f7c90ee6b546284c942ebb1c239375fb5f788e765d22ea8ff848cfe842", [:mix], [{:dns, "~> 2.0", [hex: :dns, repo: "hexpm", optional: false]}], "hexpm"}, 10 | "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, 11 | "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, 12 | "nerves": {:hex, :nerves, "0.11.0", "631693062f2fdad92b2f9d34ac7c230bbda985276b5cd99e6beff7c1a0545326", [:mix], [{:distillery, "~> 1.4", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"}, 13 | "nerves_firmware_ssh": {:hex, :nerves_firmware_ssh, "0.3.2", "2cdf126b5b264ec11c31f58b7f9933445eb065348a0b33c6762f08b1f46e87a9", [:mix], [{:nerves_runtime, "~> 0.4", [hex: :nerves_runtime, repo: "hexpm", optional: false]}], "hexpm"}, 14 | "nerves_init_gadget": {:hex, :nerves_init_gadget, "0.3.0", "4c8fdd6af9f9ad82763d7e93ab1a3f380f64d4b2804cf70acad907261b7b16be", [:mix], [{:mdns, "~> 1.0", [hex: :mdns, repo: "hexpm", optional: false]}, {:nerves_firmware_ssh, "~> 0.2", [hex: :nerves_firmware_ssh, repo: "hexpm", optional: false]}, {:nerves_network, "~> 0.3", [hex: :nerves_network, repo: "hexpm", optional: false]}, {:nerves_runtime, "~> 0.3", [hex: :nerves_runtime, repo: "hexpm", optional: false]}, {:ring_logger, "~> 0.4", [hex: :ring_logger, repo: "hexpm", optional: false]}], "hexpm"}, 15 | "nerves_network": {:hex, :nerves_network, "0.3.6", "c95779283ace071e9d12882d6a80e31edc8c476012adc61aba2ff6c306ef97b3", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:nerves_network_interface, "~> 0.4.0", [hex: :nerves_network_interface, repo: "hexpm", optional: false]}, {:nerves_wpa_supplicant, "~> 0.3.0", [hex: :nerves_wpa_supplicant, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.4", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"}, 16 | "nerves_network_interface": {:hex, :nerves_network_interface, "0.4.4", "200b1a84bc1a7fdeaf3a1e0e2d4e9b33e240b034e73f39372768d43f8690bae0", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, 17 | "nerves_runtime": {:hex, :nerves_runtime, "0.6.0", "b7336e34e65bb6c3792525587b639c4027773496a48c2eba93a78b4e7166a7ed", [:make, :mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:system_registry, "~> 0.5", [hex: :system_registry, repo: "hexpm", optional: false]}], "hexpm"}, 18 | "nerves_system_br": {:hex, :nerves_system_br, "0.17.0", "f7c0d1b6b11e9a1c187b17f2401a00956bebd5c45946bfe2a332ad26ecbf18f9", [:mix], [], "hexpm"}, 19 | "nerves_system_linter": {:hex, :nerves_system_linter, "0.2.3", "288a04f3d6dd08f97c839b5a5480c511f4c55bd193bc9dffe6f025de79108cea", [:mix], [], "hexpm"}, 20 | "nerves_system_rpi0": {:hex, :nerves_system_rpi0, "0.21.0", "7011cf5737644cda1dc50f5b01c8484a4f12588d176b6dcc36efe7d8fb33efa7", [:mix], [{:nerves, "~> 0.9", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_system_br, "0.17.0", [hex: :nerves_system_br, repo: "hexpm", optional: false]}, {:nerves_system_linter, "~> 0.2.2", [hex: :nerves_system_linter, repo: "hexpm", optional: false]}, {:nerves_toolchain_armv6_rpi_linux_gnueabi, "~> 0.13.0", [hex: :nerves_toolchain_armv6_rpi_linux_gnueabi, repo: "hexpm", optional: false]}], "hexpm"}, 21 | "nerves_toolchain_armv6_rpi_linux_gnueabi": {:hex, :nerves_toolchain_armv6_rpi_linux_gnueabi, "0.13.1", "8696fe8980dc0308fe12d92ec27f01964a56fffd5c4159b62a21618111ee9a60", [:mix], [{:nerves, "~> 0.9", [hex: :nerves, repo: "hexpm", optional: false]}, {:nerves_toolchain_ctng, "~> 1.3", [hex: :nerves_toolchain_ctng, repo: "hexpm", optional: false]}], "hexpm"}, 22 | "nerves_toolchain_ctng": {:hex, :nerves_toolchain_ctng, "1.3.1", "add96a4b12da4b50fdc5cf18517989de37cf3b329d7edf258ec794878ba06e89", [:mix], [{:nerves, "~> 0.9", [hex: :nerves, repo: "hexpm", optional: false]}], "hexpm"}, 23 | "nerves_uart": {:hex, :nerves_uart, "1.2.0", "195424116b925cd3bf9d666be036c2a80655e6ca0f8d447e277667a60005c50e", [:mix], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, 24 | "nerves_wpa_supplicant": {:hex, :nerves_wpa_supplicant, "0.3.2", "19dc7e1248336e7f542b11b2b857ceb5b088d3eb41a6ca75b7b76628dcf67aad", [:make, :mix], [{:elixir_make, "~> 0.3", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, 25 | "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"}, 26 | "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, 27 | "ring_logger": {:hex, :ring_logger, "0.4.0", "d58b2d9be6350d291fde90c734dcd56cb50b9be7cae4868163088db84a499e92", [:mix], [], "hexpm"}, 28 | "shoehorn": {:hex, :shoehorn, "0.2.0", "6aa80804145c545c59af01980d255209483b14826f53411b4a8797b24c323c20", [:mix], [{:distillery, "~> 1.0", [hex: :distillery, repo: "hexpm", optional: false]}], "hexpm"}, 29 | "socket": {:hex, :socket, "0.3.13", "98a2ab20ce17f95fb512c5cadddba32b57273e0d2dba2d2e5f976c5969d0c632", [:mix], [], "hexpm"}, 30 | "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, 31 | "system_registry": {:hex, :system_registry, "0.8.0", "09240347628b001433d18279a2759ef7237ba7361239890d8c599cca9a2fbbc2", [:mix], [], "hexpm"}, 32 | "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}, 33 | } 34 | --------------------------------------------------------------------------------