Hello everyone!
I am completely new to Nerves and this is my first “project”. I am trying to build a small server that streams the video from the picam to a simple web-page via wifi. Basically I try to test/implement the picam-http example project, using some additional network configurations from nerves-network .
I have tried two things to connect my Raspberry Pi and my laptop via wifi:
-
Turned my Raspberry Pi to an access point, creating its own network and connecting my laptop to this network.
-
Connected my Raspberry Pi to my home network with my SSID and PSK.
In the first case the created network showed up after the boot of the Raspberry Pi and I could connect to it with my laptop. In both cases I could ping the target-device after the boot with ping nerves.local for my home network and ping ip-address for the access-point network and I recevied the reply. After the boot the LED on my picam was also on. So everything seemed to work at that point.
But when I tried to access the http://nerves.local:4001/video (http://ip-address:4001/video as well), where the video from picam was supposed to be streamed, I always got “connection refused” message. (Tried http://nerves.local:4001/ and http://nerves.local/ too but got the same error). The ip-address and the domain name must be right.
Could you please help me and tell, what my mistakes are, what I am doing wrong or what I am missing?
My system is:
-
Host: Windows 10 using Virtual Box with Ubuntu 18.04.3
-
Target: Raspberry Pi 3 B+
-
Picam RB-Camera-WW2
-
SD-Card, USB-Cable
Configuration file config.exs
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
use Mix.Config
config :test_cam, target: Mix.target()
# Customize non-Elixir parts of the firmware. See
# https://hexdocs.pm/nerves/advanced-configuration.html for details.
config :nerves, :firmware, rootfs_overlay: "rootfs_overlay"
# Use shoehorn to start the main application. See the shoehorn
# docs for separating out critical OTP applications such as those
# involved with firmware updates.
config :shoehorn,
init: [:nerves_runtime, :nerves_init_gadget],
app: Mix.Project.config()[:app]
# Use Ringlogger as the logger backend and remove :console.
# See https://hexdocs.pm/ring_logger/readme.html for more information on
# configuring ring_logger.
config :logger, backends: [RingLogger]
if Mix.target() != :host do
import_config "target.exs"
end
Target configuration file target.exs
use Mix.Config
# Authorize the device to receive firmware using your public key.
# See https://hexdocs.pm/nerves_firmware_ssh/readme.html for more information
# on configuring nerves_firmware_ssh.
keys =
[
Path.join([System.user_home!(), ".ssh", "id_rsa.pub"]),
Path.join([System.user_home!(), ".ssh", "id_ecdsa.pub"]),
Path.join([System.user_home!(), ".ssh", "id_ed25519.pub"])
]
|> Enum.filter(&File.exists?/1)
if keys == [],
do:
Mix.raise("""
No SSH public keys found in ~/.ssh. An ssh authorized key is needed to
log into the Nerves device and update firmware on it using ssh.
See your project's config.exs for this error message.
""")
config :nerves_firmware_ssh,
authorized_keys: Enum.map(keys, &File.read!/1)
# Configure nerves_init_gadget.
# See https://hexdocs.pm/nerves_init_gadget/readme.html for more information.
# Setting the node_name will enable Erlang Distribution.
# Only enable this for prod if you understand the risks.
node_name = if Mix.env() != :prod, do: "test_cam"
config :test_cam, interface: :wlan0, port: 4001
config :nerves_init_gadget,
ifname: "wlan0",
address_method: :dhcp,
mdns_domain: "nerves.local",
node_name: node_name
#node_host: :mdns_domain
#### networkconfig
key_mgmt = System.get_env("NERVES_NETWORK_KEY_MGMT") || "WPA-PSK"
config :nerves_network, :default,
wlan0: [
ssid: System.get_env("NERVES_NETWORK_SSID"),
psk: System.get_env("NERVES_NETWORK_PSK"),
key_mgmt: String.to_atom(key_mgmt)
],
eth0: [
ipv4_address_method: :dhcp
]
# Import target specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
# Uncomment to use target specific configurations
# import_config "#{Mix.target()}.exs"
mix.exs
defmodule TestCam.MixProject do
use Mix.Project
@app :test_cam
@version "0.1.0"
@all_targets [:rpi, :rpi0, :rpi2, :rpi3, :rpi3a, :rpi4, :bbb, :x86_64]
def project do
[
app: @app,
version: @version,
elixir: "~> 1.9",
archives: [nerves_bootstrap: "~> 1.6"],
start_permanent: Mix.env() == :prod,
build_embedded: true,
aliases: [loadconfig: [&bootstrap/1]],
deps: deps(),
releases: [{@app, release()}],
preferred_cli_target: [run: :host, test: :host]
]
end
# Starting nerves_bootstrap adds the required aliases to Mix.Project.config()
# Aliases are only added if MIX_TARGET is set.
def bootstrap(args) do
Application.start(:nerves_bootstrap)
Mix.Task.run("loadconfig", args)
end
# Run "mix help compile.app" to learn about applications.
def application do
[
mod: {TestCam.Application, []},
extra_applications: [:logger, :runtime_tools]
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# Dependencies for all targets
{:nerves, "~> 1.5.0", runtime: false},
{:shoehorn, "~> 0.6"},
{:ring_logger, "~> 0.6"},
{:toolshed, "~> 0.2"},
{:picam, "~> 0.4.0"},
{:cowboy, "~> 1.0.0"},
{:plug, "~> 1.0"},
# Dependencies for all targets except :host
{:nerves_runtime, "~> 0.6", targets: @all_targets},
{:nerves_init_gadget, "~> 0.4", targets: @all_targets},
{:nerves_firmware_ssh, "~> 0.3", targets: @all_targets},
# Dependencies for specific targets
{:nerves_system_rpi, "~> 1.8", runtime: false, targets: :rpi},
{:nerves_system_rpi0, "~> 1.8", runtime: false, targets: :rpi0},
{:nerves_system_rpi2, "~> 1.8", runtime: false, targets: :rpi2},
{:nerves_system_rpi3, "~> 1.8", runtime: false, targets: :rpi3},
{:nerves_system_rpi3a, "~> 1.8", runtime: false, targets: :rpi3a},
{:nerves_system_rpi4, "~> 1.8", runtime: false, targets: :rpi4},
{:nerves_system_bbb, "~> 2.3", runtime: false, targets: :bbb},
{:nerves_system_x86_64, "~> 1.8", runtime: false, targets: :x86_64},
]
end
def release do
[
overwrite: true,
cookie: "#{@app}_cookie",
include_erts: &Nerves.Release.erts/0,
steps: [&Nerves.Release.init/1, :assemble],
strip_beams: Mix.env() == :prod
]
end
end
application.ex
defmodule TestCam.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
use Application
def start(_type, _args) do
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
Picam.Camera.start_link
opts = [strategy: :one_for_one, name: TestCam.Supervisor]
children =
[
# Children for all targets
# Starts a worker by calling: TestCam.Worker.start_link(arg)
# {TestCam.Worker, arg},
] ++ children(target())
Supervisor.start_link(children, opts)
end
# List all child processes to be supervised
def children(:host) do
[
# Children that only run on the host
# Starts a worker by calling: TestCam.Worker.start_link(arg)
# {TestCam.Worker, arg},
]
end
def children(_target) do
[
# Children for all targets except host
# Starts a worker by calling: TestCam.Worker.start_link(arg)
# {TestCam.Worker, arg},
Plug.Adapters.Cowboy.child_spec(scheme: :http, plug: TestCam.Router, options: [port: 4001])
]
end
def target() do
Application.get_env(:test_cam, :target)
end
end
Thanks in advance and please let me know, if you need any additional information about the system or code.