### Initiate pppd Connection with CLI Options Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/lte-ready-only.md Use this command to start a pppd connection when unable to write an options file to the filesystem. Ensure the chat script path and serial device are correct for your setup. ```bash pppd connect "/usr/sbin/chat -v -f /tmp/nerves-network/chatscripts/twilio" /dev/ttyUSB0 115200 noipdefault usepeerdns defaultroute persist noauth ``` -------------------------------- ### Example Log Output Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/LTE.md This is an example of the log output you might see after successfully connecting to the LTE network. It shows the DHCP client acquiring an IP address and the PPP daemon establishing a connection. ```log Jan 1 00:53:46 nettest daemon.info dhcpcd[112]: wwan0: waiting for carrier Jan 1 00:53:46 nettest daemon.info dhcpcd[112]: wwan0: carrier acquired Jan 1 00:53:46 nettest daemon.info dhcpcd[112]: wwan0: IAID 10:1f:00:00 Jan 1 00:53:46 nettest daemon.info dhcpcd[112]: wwan0: adding address fe80::453c:384b:9d79:45cc Jan 1 00:53:46 nettest daemon.info dhcpcd[112]: wwan0: soliciting an IPv6 router Jan 1 00:53:47 nettest daemon.info dhcpcd[112]: wwan0: soliciting a DHCP lease Jan 1 00:53:52 nettest daemon.info dhcpcd[112]: wwan0: probing for an IPv4LL address Jan 1 00:53:57 nettest daemon.info dhcpcd[112]: wwan0: using IPv4LL address 169.254.62.145 Jan 1 00:53:57 nettest daemon.info dhcpcd[112]: wwan0: adding route to 169.254.0.0/16 Jan 1 00:53:57 nettest daemon.info dhcpcd[112]: wwan0: adding default route Jan 1 00:53:59 nettest daemon.warn dhcpcd[112]: wwan0: no IPv6 Routers available Jan 1 00:55:30 nettest daemon.notice pppd[213]: pppd 2.4.7 started by root, uid 0 Jan 1 00:55:31 nettest local2.info chat[214]: abort on (BUSY) Jan 1 00:55:31 nettest local2.info chat[214]: abort on (NO CARRIER) Jan 1 00:55:31 nettest local2.info chat[214]: abort on (NO DIALTONE) Jan 1 00:55:31 nettest local2.info chat[214]: abort on (NO DIAL TONE) Jan 1 00:55:31 nettest local2.info chat[214]: abort on (NO ANSWER) Jan 1 00:55:31 nettest local2.info chat[214]: abort on (DELAYED) Jan 1 00:55:31 nettest local2.info chat[214]: timeout set to 10 seconds Jan 1 00:55:31 nettest local2.info chat[214]: report (CONNECT) Jan 1 00:55:31 nettest local2.info chat[214]: send (AT^M) Jan 1 00:55:31 nettest local2.info chat[214]: expect (OK) Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: OK Jan 1 00:55:31 nettest local2.info chat[214]: -- got it Jan 1 00:55:31 nettest local2.info chat[214]: send (ATH^M) Jan 1 00:55:31 nettest local2.info chat[214]: expect (OK) Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: OK Jan 1 00:55:31 nettest local2.info chat[214]: -- got it Jan 1 00:55:31 nettest local2.info chat[214]: send (ATZ^M) Jan 1 00:55:31 nettest local2.info chat[214]: expect (OK) Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: OK Jan 1 00:55:31 nettest local2.info chat[214]: -- got it Jan 1 00:55:31 nettest local2.info chat[214]: send (ATQ0^M) Jan 1 00:55:31 nettest local2.info chat[214]: expect (OK) Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: ^M Jan 1 00:55:31 nettest local2.info chat[214]: OK Jan 1 00:55:31 nettest local2.info chat[214]: -- got it Jan 1 00:55:31 nettest local2.info chat[214]: send (AT+CGDCONT=1,"IP","wireless.twilio.com"^M) Jan 1 00:55:32 nettest local2.info chat[214]: expect (OK) Jan 1 00:55:32 nettest local2.info chat[214]: ^M Jan 1 00:55:32 nettest local2.info chat[214]: ^M Jan 1 00:55:32 nettest local2.info chat[214]: OK Jan 1 00:55:32 nettest local2.info chat[214]: -- got it Jan 1 00:55:32 nettest local2.info chat[214]: send (ATDT*99***1#^M) Jan 1 00:55:32 nettest local2.info chat[214]: expect (CONNECT) Jan 1 00:55:32 nettest local2.info chat[214]: ^M Jan 1 00:55:32 nettest local2.info chat[214]: ^M Jan 1 00:55:32 nettest local2.info chat[214]: CONNECT Jan 1 00:55:32 nettest local2.info chat[214]: -- got it Jan 1 00:55:32 nettest local2.info chat[214]: send (^M) Jan 1 00:55:32 nettest daemon.info pppd[213]: Serial connection established. Jan 1 00:55:32 nettest daemon.info pppd[213]: Using interface ppp0 Jan 1 00:55:32 nettest daemon.notice pppd[213]: Connect: ppp0 <--> /dev/ttyUSB0 Jan 1 00:55:35 nettest daemon.warn pppd[213]: Could not determine remote IP address: defaulting to 10.64.64.64 ``` -------------------------------- ### Start wpa_supplicant daemon Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/WiFi-read-only-fs-setup.md This command starts the wpa_supplicant process in the background to manage WiFi connections using the specified configuration file. ```bash wpa_supplicant -B -i wlan0 -c /tmp/nerves-network/wpa_supplicant.conf -d ``` -------------------------------- ### Start dnsmasq Service Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/AP-mode-basic.md Start the dnsmasq service to enable DNS and DHCP services for the AP network. This command should be run after bringing up the wlan0 interface. ```bash /etc/init.d/S80dnsmasq start ``` -------------------------------- ### Bring wlan0 interface up Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/WiFi-read-only-fs-setup.md Activates the wlan0 network interface after wpa_supplicant has been started. ```bash ip link set wlan0 up ``` -------------------------------- ### Get All Network Properties by Prefix Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Use `VintageNet.get_by_prefix/1` to retrieve all properties that match a given prefix. This example retrieves all properties related to interfaces. ```elixir iex> VintageNet.get_by_prefix([]) [ {["interface", "eth0", "connection"], :internet}, {["interface", "eth0", "state"], :configured}, {["interface", "eth0", "type"], VintageNetEthernet}, {["interface", "wlan0", "connection"], :internet}, {["interface", "wlan0", "state"], :configured}, {["interface", "wlan0", "type"], VintageNetWiFi} ] ``` -------------------------------- ### Elixir Nerves Runtime Command for Network Interface Up Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi-WPA2.md Example of initiating the 'ifup' command for the wlan0 interface using Nerves.Runtime.cmd in Elixir. This demonstrates the expected output during the DHCP and WPA supplicant process. ```elixir Nerves.Runtime.cmd("ifup", ["wlan0"], :info) [ TONS OF WPA OUTPUT ] 00:00:19.900 [info] Daemonize.. 00:00:19.900 [info] 00:00:19.921 [info] udhcpc: started, v1.27.2 00:00:19.921 [info] 00:00:20.010 [info] udhcpc: sending discover 00:00:20.010 [info] 00:00:23.103 [info] udhcpc: sending discover 00:00:23.103 [info] 00:00:26.183 [info] udhcpc: sending discover 00:00:26.183 [info] 00:00:29.242 [info] udhcpc: sending select for 192.168.86.129 00:00:29.242 [info] 00:00:29.320 [info] udhcpc: lease of 192.168.86.129 obtained, lease time 86400 00:00:29.320 [info] 00:00:29.331 [info] deleting routers 00:00:29.331 [info] 00:00:29.356 [info] adding dns 192.168.86.1 00:00:29.356 [info] {%Nerves.Runtime.OutputLogger{level: :info}, 0} ``` -------------------------------- ### Configure Multiple WiFi Networks (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Dynamically configure multiple WiFi networks using `VintageNet.configure/2`. This example uses DHCP for IP assignment. It's useful for devices that need to connect to different networks frequently. ```elixir VintageNet.configure("wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{key_mgmt: :wpa_psk, ssid: "my_network_ssid", psk: "a_passphrase_or_psk" }, %{key_mgmt: :wpa_psk, ssid: "another_ssid", psk: "a_passphrase_or_psk" }, ] }, ipv4: %{method: :dhcp}, }) ``` -------------------------------- ### Run hostapd Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/AP-mode-basic.md Manually start hostapd with its configuration file to enable the Access Point functionality. This command runs in the foreground, allowing direct observation of logs. ```bash hostapd /etc/hostapd/hostapd.conf ``` -------------------------------- ### Nerves Runtime Command Execution and DHCP Lease Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi,-DHCP-Wired.md Example output from running Nerves.Runtime.cmd("ifup", ["-a"]) showing the DHCP process for a wireless connection. ```elixir Nerves.Runtime.cmd("ifup", ["-a"], :info) [ Couldn't capture eth0 logs, but it came up ] [ TONS OF WPA LOGS ] 00:00:55.324 [info] Daemonize.. 00:00:55.324 [info] 00:00:55.343 [info] udhcpc: started, v1.27.2 00:00:55.343 [info] 00:00:55.410 [info] udhcpc: sending discover 00:00:55.410 [info] 00:00:58.513 [info] udhcpc: sending discover 00:00:58.513 [info] 00:01:01.593 [info] udhcpc: sending discover 00:01:01.593 [info] 00:01:01.670 [info] udhcpc: sending select for 192.168.86.129 00:01:01.670 [info] 00:01:01.750 [info] udhcpc: lease of 192.168.86.129 obtained, lease time 86400 00:01:01.750 [info] 00:01:01.761 [info] deleting routers 00:01:01.761 [info] 00:01:01.786 [info] adding dns 192.168.86.1 ``` -------------------------------- ### Configure Multiple WiFi Networks (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Configure multiple WiFi networks for automatic connection. This example uses DHCP for the IPv4 configuration. Ensure that networks requiring static IPs are not mixed with DHCP-enabled networks in the same configuration. ```elixir config :vintage_net, config: [ {"wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{key_mgmt: :wpa_psk, ssid: "my_network_ssid", psk: "a_passphrase_or_psk" }, %{key_mgmt: :wpa_psk, ssid: "another_ssid", psk: "a_passphrase_or_psk" }, ] }, ipv4: %{method: :dhcp}, }} ] ``` -------------------------------- ### Configure VintageNet with Ethernet and WiFi Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Configure VintageNet in your config.exs file to set up network interfaces. This example shows DHCP configuration for both Ethernet and WiFi, including a sample WiFi network. ```elixir config :vintage_net, regulatory_domain: "US", # Change to match your area config: [ {"eth0", %{ type: VintageNetEthernet, ipv4: %{ method: :dhcp } }}, {"wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{ key_mgmt: :wpa_psk, ssid: "Your WiFi SSID", psk: "passphrase or psk", } ] }, ipv4: %{method: :dhcp}, } } ] ``` -------------------------------- ### Bring down network interfaces Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/WiFi-read-only-fs-setup.md Use these commands to ensure a clean networking state by disabling wlan0 and eth0 interfaces before starting WiFi setup. ```bash ip link set wlan0 down ip link set eth0 down ``` -------------------------------- ### Get VintageNet Interface Information Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Use VintageNet.info to verify the configuration and connection status of network interfaces. This command provides details about all interfaces, available interfaces, and specific configuration for each. ```elixir iex> VintageNet.info ``` -------------------------------- ### Get Current VintageNet Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md View the current network configuration by calling VintageNet.info in an IEx prompt. ```elixir VintageNet.info ``` -------------------------------- ### Get a Specific Network Property Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Use `VintageNet.get/1` to retrieve the value of a specific network property. This example shows how to get the connection status for the eth0 interface. ```elixir iex> VintageNet.get(["interface", "eth0", "connection"]) :internet ``` -------------------------------- ### Configure Static IP for WiFi (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Use this configuration in your `config/config.exs` to set up a WiFi network with a static IPv4 address. Ensure the SSID and PSK are correct for your network. ```elixir config :vintage_net, config: [ {"wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{key_mgmt: :wpa_psk, ssid: "my_network_ssid", psk: "a_passphrase_or_psk" } ] }, ipv4: %{ method: :static, address: "192.168.9.232", prefix_length: 24, gateway: "192.168.9.1", name_servers: ["1.1.1.1"] } }} ] ``` -------------------------------- ### Configure Enterprise WiFi PEAPv0 (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Set up a WiFi connection for enterprise networks using PEAPv0 authentication. This requires providing identity, password, and specifying the EAP and phase2 authentication methods. ```elixir config :vintage_net, config: [ {"wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{key_mgmt: :wpa_eap, ssid: "my_network_ssid", identity: "username", password: "password", eap: "PEAP", phase2: "auth=MSCHAPV2" } ] }, ipv4: %{method: :dhcp}, }} ] ``` -------------------------------- ### Configure Static IP for WiFi (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Use this `VintageNet.configure/2` call in IEx or your application code to dynamically set up a WiFi network with a static IPv4 address. This is useful for testing or when network details are not known at compile time. ```elixir VintageNet.configure("wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{key_mgmt: :wpa_psk, ssid: "my_network_ssid", psk: "a_passphrase_or_psk" } ] }, ipv4: %{ method: :static, address: "192.168.9.232", prefix_length: 24, gateway: "192.168.9.1", name_servers: ["1.1.1.1"] } }) ``` -------------------------------- ### Configure WiFi with WPA2 PSK (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Connect to a password-protected WiFi network using WPA2 PSK at run-time by calling VintageNet.configure in IEx. Replace placeholders with your network's SSID and passphrase. ```elixir VintageNet.configure("wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{ key_mgmt: :wpa_psk, ssid: "my_network_ssid", psk: "a_passphrase_or_psk" } ] }, ipv4: %{method: :dhcp}, }) ``` -------------------------------- ### Bring up WiFi Interface using ifup Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Static-WiFi-Host-mode.md Executes the 'ifup' command to bring the wlan0 network interface up, applying the configurations defined in `/etc/network/interfaces`. ```elixir iex()> Nerves.Runtime.cmd("ifup", ["wlan0"], :info) ``` -------------------------------- ### Basic wpa_supplicant configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/WiFi-read-only-fs-setup.md This is a minimal configuration file for wpa_supplicant, which needs to be written to `/tmp/nerves-network/wpa_supplicant.conf` with your specific SSID and PSK. ```text ctrl_interface=/var/run/wpa_supplicant network={ ssid="My SSID" psk="My PSK" } ``` -------------------------------- ### Advanced wpa_supplicant Configuration (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Use this to provide a custom wpa_supplicant.conf content for precise control over supplicant settings. The provided string is copied directly. ```elixir config :vintage_net, config: [ {"wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ wpa_supplicant_conf: """ network={ ssid="home" key_mgmt=WPA-PSK psk="very secret passphrase" } """ }, ipv4: %{method: :dhcp} }} ] ``` -------------------------------- ### Subscribe to Network Property Changes Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Use `VintageNet.subscribe/1` to subscribe to changes for a given property or its children. This example subscribes to changes on the eth0 interface. ```elixir iex> VintageNet.subscribe(["interface", "eth0"]) :ok ``` -------------------------------- ### Testing WiFi Connection with Nerves Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi-None.md Execute the 'ifup' command to bring up the wlan0 interface and observe the DHCP lease process. ```elixir iex(6)> Nerves.Runtime.cmd("ifup", ["wlan0"], :info) 00:00:25.002 [info] Daemonize.. 00:00:25.002 [info] 00:00:25.019 [info] udhcpc: started, v1.27.2 00:00:25.019 [info] 00:00:25.130 [info] udhcpc: sending discover 00:00:25.130 [info] 00:00:28.213 [info] udhcpc: sending discover 00:00:28.213 [info] 00:00:31.286 [info] udhcpc: sending select for 192.168.43.95 00:00:31.286 [info] 00:00:31.370 [info] udhcpc: lease of 192.168.43.95 obtained, lease time 3600 00:00:31.370 [info] 00:00:31.381 [info] deleting routers 00:00:31.381 [info] 00:00:31.405 [info] adding dns 192.168.43.1 00:00:31.405 [info] {%Nerves.Runtime.OutputLogger{level: :info}, 0} ``` -------------------------------- ### hostapd AP-ENABLED Log Output Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/AP-mode-basic.md Example log output from hostapd indicating that the AP has been successfully enabled on the wlan0 interface. This confirms the AP is broadcasting the configured SSID. ```log # hostapd /etc/hostapd/hostapd.conf Configuration file: /etc/hostapd/hostapd.conf Failed to create interface mon.wlan0: -95 (Operation not supported) wlan0: Could not connect to kernel driver Using interface wlan0 with hwaddr b8:27:eb:13:a3:06 and ssid "Pi3-AP" [ 5833.256928] IPv6: ADDRCONF(NETDEV_CHANGE): wlan0: link becomes ready wlan0: interface state UNINITIALIZED->ENABLED wlan0: AP-ENABLED ``` -------------------------------- ### Verify PPP Interface with ip link Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/LTE.md After establishing a PPP connection, use 'ip link show' to verify that the 'ppp0' interface is present and active. This command lists all network interfaces. ```bash $ ip link show ``` ```text 1: lo: mtu 65536 qdisc noop qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: wlan0: mtu 1500 qdisc pfifo_fast qlen 1000 link/ether b8:27:eb:13:a3:06 brd ff:ff:ff:ff:ff:ff 3: eth0: mtu 1500 qdisc pfifo_fast qlen 1000 link/ether b8:27:eb:46:f6:53 brd ff:ff:ff:ff:ff:ff 4: wwan0: mtu 1500 qdisc pfifo_fast qlen 1000 link/ether 00:1e:10:1f:00:00 brd ff:ff:ff:ff:ff:ff 5: ppp0: mtu 1500 qdisc pfifo_fast qlen 3 link/ppp ``` -------------------------------- ### DHCP Configuration for wlan0 Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi-WEP.md Configures the `wlan0` interface to obtain an IP address via DHCP. It also includes commands to start `wpa_supplicant` before the interface comes up and to kill it after the interface goes down. ```config iface wlan0 inet dhcp pre-up wpa_supplicant -B -Dwext -iwlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf post-down killall -q wpa_supplicant ``` -------------------------------- ### Process Subscription Messages Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md When a subscribed property changes, a message is sent to the process. The message format is `{VintageNet, name, old_value, new_value, metadata}`. This example shows how to flush and inspect such a message. ```elixir iex> flush {VintageNet, ["interface", "eth0", "state"], :configuring, :configured, %{old_timestamp: 123456, new_timestamp: 124456}} ``` -------------------------------- ### Network Interfaces Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Two-DHCP-Wired-Ethernets.md This configuration file sets up two Ethernet interfaces, eth0 and eth1, to automatically come up on boot and obtain IP addresses using DHCP. ```config auto eth0 iface eth0 inet dhcp auto eth1 iface eth1 inet dhcp ``` -------------------------------- ### Network Interface Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi-None.md Configure the wlan0 interface to use DHCP and pre-up wpa_supplicant for authentication. ```config auto wlan0 iface wlan0 inet dhcp pre-up wpa_supplicant -B w -i wlan0 -c /etc/wpa_supplicant.conf -dd post-down killall -q wpa_supplicant ``` -------------------------------- ### Configure Mesh Device Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Configures a device to connect to an existing mesh network. This setup assumes the mesh is bridged on another device and allows the mesh interface to obtain an IP address via DHCP. ```elixir mesh0_config = %{ type: VintageNetWiFi, vintage_net_wifi: %{ user_mpm: 1, # mesh creates a "virtual" interface based on # this interface name root_interface: "wlan0", networks: [ %{key_mgmt: :none, ssid: "my-mesh", frequency: 2432, mode: :mesh} ] }, # the mesh is bridged on the other # device, so we can use dhcp now ipv4: %{method: :dhcp}, } VintageNet.configure("mesh0", mesh0_config) ``` -------------------------------- ### Network Interfaces Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-Wired-Ethernet.md This configuration file sets up the 'eth0' interface to use DHCP for obtaining an IP address. It ensures the interface is brought up automatically on boot. ```config auto eth0 iface eth0 inet dhcp ``` -------------------------------- ### Implement a Custom VintageNet Power Manager Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md This Elixir module implements the VintageNet.PowerManager behaviour to control a network interface's power state using GPIO pins. It defines functions for initialization, powering on, starting power-off, and powering off the interface. ```elixir defmodule MyPowerManager do @behaviour VintageNet.PowerManager @reset_n_gpio 4 @power_on_hold_time 5 * 60000 @min_powered_off_time 5000 defstruct reset_n: nil @impl VintageNet.PowerManager def init(_args) do {:ok, reset_n} = Circuits.GPIO.open(@reset_n_gpio, :output) {:ok, %__MODULE__{reset_n: reset_n}} end @impl VintageNet.PowerManager def power_on(state) do # Do whatever is necessary to turn the network interface on Circuits.GPIO.write(state.reset_n, 1) {:ok, state, @power_on_hold_time} end @impl VintageNet.PowerManager def start_powering_off(state) do # If there's a graceful power off, start it here and return # the max time it takes. {:ok, state, 0} end @impl VintageNet.PowerManager def power_off(state) do # Disable the network interface Circuits.GPIO.write(state.reset_n, 0) {:ok, state, @min_powered_off_time} end end ``` -------------------------------- ### Inspect Built-in WiFi Interface (Beaglebone Green WiFi) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Predictable-Interface-Names.md Examine the properties of the Beaglebone Green WiFi's built-in wireless interface using `udevadm info`. ```bash debian@beaglebone:~$ udevadm info /sys/class/net/wlan1 P: /devices/platform/ocp/47810000.mmc/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/wl18xx.1.auto/net/wlan1 L: 0 E: DEVPATH=/devices/platform/ocp/47810000.mmc/mmc_host/mmc2/mmc2:0001/mmc2:0001:2/wl18xx.1.auto/net/wlan1 E: DEVTYPE=wlan E: INTERFACE=wlan1 E: IFINDEX=8 E: SUBSYSTEM=net E: USEC_INITIALIZED=87963345 E: net.ifnames=0 E: ID_NET_NAMING_SCHEME=v240 E: ID_NET_NAME_MAC=wlx884aea628a7c E: ID_OUI_FROM_DATABASE=Texas Instruments E: ID_PATH=platform-47810000.mmc-platform-wl18xx.1.auto E: ID_PATH_TAG=platform-47810000_mmc-platform-wl18xx_1_auto E: ID_NET_DRIVER=wl18xx_driver E: ID_NET_LINK_FILE=/lib/systemd/network/99-default.link E: SYSTEMD_ALIAS=/sys/subsystem/net/devices/wlan1 E: TAGS=:systemd: ``` -------------------------------- ### Enable IP Forwarding and NAT for WAN Sharing Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Enables IP forwarding and configures iptables for Network Address Translation (NAT) to share a WAN connection. Requires a custom Nerves system with iptables installed. The WAN interface is specified as 'eth0'. ```elixir wan = "eth0" cmd "sysctl -w net.ipv4.ip_forward=1" cmd "iptables -t nat -A POSTROUTING -o #{wan} -j MASQUERADE" cmd "iptables --append FORWARD --in-interface wlan0 -j ACCEPT" # Only needed if the connection is blocked otherwise (like a default policy of DROP) cmd "iptables -A INPUT -i #{wan} -m state --state RELATED,ESTABLISHED -j ACCEPT" ``` -------------------------------- ### View Connection Logs Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/LTE.md To verify the connection status and troubleshoot any issues, view the system messages. This command displays logs that include details about the DHCP client and PPP daemon. ```bash $ cat /var/log/messages ``` -------------------------------- ### Configure Wired Ethernet with DHCP (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Set up a wired Ethernet interface to use DHCP by adding this configuration to your config.exs file. ```elixir config :vintage_net, config: [ {"eth0", %{type: VintageNetEthernet, ipv4: %{method: :dhcp}}} ] ``` -------------------------------- ### WPA Supplicant Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi-WPA2.md Set up WPA supplicant to connect to a WPA2-PSK secured WiFi network. This snippet should be placed in `/etc/wpa_supplicant.conf`. ```config ctrl_interface=/var/run/wpa_supplicant ap_scan=1 network={ ssid="FarmBotHQ" scan_ssid=1 proto=WPA RSN key_mgmt=WPA-PSK pairwise=CCMP TKIP group=CCMP TKIP psk="SUPER SECRET" } ``` -------------------------------- ### Configure Static IP for WiFi AP Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Static-WiFi-Host-mode.md Sets up the wlan0 interface with a static IP address, netmask, and gateway. It also configures DNS settings and runs wpa_supplicant and udhcpd before bringing the interface up, and stops them after bringing it down. ```shell auto wlan0 iface wlan0 inet static address 10.0.0.1 netmask 255.255.255.0 network 10.0.0.0 broadcast 10.0.0.255 gateway 10.0.0.1 dns-nameservers 10.0.0.1 1.1.1.1 dns-domain acme.com dns-search acme.com pre-up wpa_supplicant -B w -i wlan0 -c /etc/wpa_supplicant.conf -dd; udhcpd /etc/udhcpcd.conf post-down killall -q wpa_supplicant; killall -q udhcpd ``` -------------------------------- ### Configure WiFi with WPA2 PSK (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Connect to a password-protected WiFi network using WPA2 PSK by adding this configuration to your config.exs file. Replace placeholders with your network's SSID and passphrase. ```elixir config :vintage_net, config: [ {"wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{ key_mgmt: :wpa_psk, ssid: "my_network_ssid", psk: "a_passphrase_or_psk" } ] }, ipv4: %{method: :dhcp}, }} ] ``` -------------------------------- ### Configure Enterprise WiFi PEAPv0 (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Dynamically configure enterprise WiFi using PEAPv0 authentication via `VintageNet.configure/2`. This is useful for devices connecting to corporate networks that use this security protocol. ```elixir VintageNet.configure("wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{key_mgmt: :wpa_eap, ssid: "my_network_ssid", identity: "username", password: "password", eap: "PEAP", phase2: "auth=MSCHAPV2" } ] }, ipv4: %{method: :dhcp}, }) ``` -------------------------------- ### Advanced wpa_supplicant Configuration (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Dynamically configure wpa_supplicant with custom settings using the 'wpa_supplicant_conf' option. This allows for fine-grained control over WiFi connection parameters. ```elixir VintageNet.configure("wlan0", %{ type: VintageNetWiFi, vintage_net_wifi: %{ wpa_supplicant_conf: """ network={ ssid="home" key_mgmt=WPA-PSK psk="very secret passphrase" } """ }, ipv4: %{method: :dhcp} }) ``` -------------------------------- ### Initiate DHCP Client and Observe Output Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-Wired-Ethernet.md This Elixir code snippet demonstrates how to execute the 'ifup eth0' command using Nerves.Runtime.cmd and captures the informational output from the udhcpc client during the DHCP process. This is useful for debugging network connectivity. ```elixir iex(1)> Nerves.Runtime.cmd("ifup", ["eth0"], :info) 00:00:30.469 [info] udhcpc: started, v1.27.2 00:00:30.469 [info] 00:00:30.570 [info] udhcpc: sending discover 00:00:30.570 [info] 00:00:33.653 [info] udhcpc: sending discover 00:00:33.653 [info] 00:00:33.740 [info] udhcpc: sending select for 192.168.86.127 00:00:33.740 [info] 00:00:33.830 [info] udhcpc: lease of 192.168.86.127 obtained, lease time 86400 00:00:33.830 [info] 00:00:33.840 [info] deleting routers 00:00:33.840 [info] 00:00:33.878 [info] adding dns 192.168.86.1 00:00:33.878 [info] {%Nerves.Runtime.OutputLogger{level: :info}, 0} ``` -------------------------------- ### Network Interfaces Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi,-DHCP-Wired.md Configure DHCP for both eth0 and wlan0. Includes pre-up command for wpa_supplicant on the wireless interface. ```config auto eth0 iface eth0 inet dhcp auto wlan0 iface wlan0 inet dhcp pre-up wpa_supplicant -B w -i wlan0 -c /etc/wpa_supplicant.conf -dd post-down killall -q wpa_supplicant ``` -------------------------------- ### Bringing Up Ethernet Interface Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Static-Wired-Ethernet.md Use this command to bring up the eth0 network interface after configuring its static IP settings. This command requires root privileges. ```elixir Nerves.Runtime.cmd("ifup", ["eth0"], :info) ``` -------------------------------- ### Verify Ethernet Interface Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Static-Wired-Ethernet-IPv6.md This command displays the configuration of the `eth0` interface, including its IPv6 addresses (link-local and global), and network statistics. ```iex Nerves.Runtime.cmd("ifconfig", ["eth0"], :info) ``` -------------------------------- ### Configure Wired Ethernet with Static IP (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Configure a static IP address for a wired Ethernet interface at run-time by calling VintageNet.configure in IEx. Update IP details as needed. ```elixir VintageNet.configure("eth0", %{ type: VintageNetEthernet, ipv4: %{ method: :static, address: "192.168.9.232", prefix_length: 24, gateway: "192.168.9.1", name_servers: ["1.1.1.1"] } }) ``` -------------------------------- ### WPA Supplicant Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi,-DHCP-Wired.md Sets up the WPA supplicant to connect to a specific WiFi network with a pre-shared key. ```config ctrl_interface=/var/run/wpa_supplicant ap_scan=1 network={ ssid="FarmBotHQ" scan_ssid=1 proto=WPA RSN key_mgmt=WPA-PSK pairwise=CCMP TKIP group=CCMP TKIP psk="SUPER SECRET" } ``` -------------------------------- ### Verify IP Address for PPP Interface Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/LTE.md Use 'ip addr show ppp0' to confirm that the 'ppp0' interface has been assigned an IP address. This is crucial for network connectivity. ```bash $ ip addr show ppp0 ``` ```text 5: ppp0: mtu 1500 qdisc pfifo_fast qlen 3 link/ppp inet 26.35.123.110 peer 10.64.64.64/32 scope global ppp0 valid_lft forever preferred_lft forever ``` -------------------------------- ### WPA Supplicant Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/DHCP-WiFi-None.md Set up wpa_supplicant for an open network, specifying the SSID and disabling security. ```config ctrl_interface=/var/run/wpa_supplicant ap_scan=1 network={ ssid="AndroidAP" scan_ssid=1 key_mgmt=NONE } ``` -------------------------------- ### Display Network Interface Details with ifconfig Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Utilize the ifconfig command (often available via Toolshed) to display detailed information about network interfaces, including their flags, IP addresses, and hardware addresses. ```shell iex> ifconfig ``` -------------------------------- ### Configure WiFi AP with WPA2 Security (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Configure a WiFi access point with WPA2-PSK security. Ensure 'proto' is set to 'RSN' for WPA2 compatibility. ```elixir config :vintage_net, config: [ {"wlan0", %{type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{mode: :ap, key_mgmt: :wpa_psk, proto: "RSN", pairwise: "CCMP", group: "CCMP", ssid: "test ssid", psk: "secret123" } ] }, ipv4: %{ method: :static, address: "192.168.24.1", netmask: "255.255.255.0" }, dhcpd: %{ start: "192.168.24.2", end: "192.168.24.10", options: %{ dns: ["1.1.1.1", "1.0.0.1"], subnet: "255.255.255.0", router: ["192.168.24.1"] } } } } ] ``` -------------------------------- ### Add VintageNet and Technologies to Dependencies Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Add VintageNet and the desired technology dependencies to your project's mix.exs file. Ensure to use compatible versions. ```elixir def deps do #.. {:vintage_net, "~> 0.13"}, {:vintage_net_ethernet, "~> 0.11"}, {:vintage_net_wifi, "~> 0.12"}, #.. end ``` -------------------------------- ### Configure Link-Local Ethernet Interface Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Link-local-Wired-Ethernet.md This snippet shows the basic configuration for an Ethernet interface (`eth0`) to use link-local addressing. Ensure this configuration is applied to the `/etc/network/interfaces` file. ```config auto eth0 iface eth0 inet ? ``` -------------------------------- ### Verifying Ethernet Interface Configuration Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Static-Wired-Ethernet.md After bringing up the interface, use this command to verify the assigned IP address, netmask, and other network interface details. This command requires root privileges. ```elixir Nerves.Runtime.cmd("ifconfig", [], :info) ``` -------------------------------- ### Configure WiFi AP without Security (Compile-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Use this configuration to set up a WiFi access point with no security. This is suitable for testing or environments where security is not a concern. ```elixir config :vintage_net, config: [ {"wlan0", %{type: VintageNetWiFi, vintage_net_wifi: %{ networks: [ %{mode: :ap, ssid: "test ssid", key_mgmt: :none } ] }, ipv4: %{ method: :static, address: "192.168.24.1", netmask: "255.255.255.0" }, dhcpd: %{ start: "192.168.24.2", end: "192.168.24.10", options: %{ dns: ["1.1.1.1", "1.0.0.1"], subnet: "255.255.255.0", router: ["192.168.24.1"] } } } } ] ``` -------------------------------- ### Static IP Configuration for Ethernet Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/notes/Static-Wired-Ethernet.md This configuration file sets up a static IP address, netmask, gateway, and DNS servers for the eth0 interface. Ensure this file is placed at /etc/network/interfaces. ```config auto eth0 iface eth0 inet static address 192.168.86.127 netmask 255.255.255.0 network 192.168.86.0 broadcast 192.168.86.255 gateway 192.168.86.1 dns-nameservers 192.168.86.1 8.8.8.8 ``` -------------------------------- ### Configure Wired Ethernet with DHCP (Run-time) Source: https://github.com/nerves-networking/vintage_net/blob/main/docs/cookbook.md Configure a wired Ethernet interface to use DHCP at run-time by calling VintageNet.configure in IEx. ```elixir VintageNet.configure("eth0", %{type: VintageNetEthernet, ipv4: %{method: :dhcp}}) ``` -------------------------------- ### Identify Network Interface Hardware Paths Source: https://github.com/nerves-networking/vintage_net/blob/main/README.md Use VintageNet.match to discover the hardware paths associated with your network interfaces. This is the first step in configuring predictable names. ```elixir iex> VintageNet.match(["interface", :_, "hw_path"]) [ {["interface", "eth0", "hw_path"], "/devices/platform/ocp/4a100000.ethernet"}, {["interface", "lo", "hw_path"], "/devices/virtual"}, {["interface", "wlan0", "hw_path"], "/devices/platform/ocp/47400000.usb/47401c00.usb/musb-hdrc.1/usb2/2-1/2-1:1.0"}, {["interface", "wlan1", "hw_path"], "/devices/platform/ocp/47400000.usb/47401400.usb/musb-hdrc.0/usb1/1-1/1-1:1.4"} ] ```