-
Notifications
You must be signed in to change notification settings - Fork 8
feat: addition of the APIRequest example in Elixir folder #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
8cf0ac9
c54122d
d9b6aca
2bedd34
7fada32
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Used by "mix format" | ||
[ | ||
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
_build/* | ||
_checkouts/* | ||
src/config.erl | ||
rebar.lock | ||
*.avm | ||
**.beam |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# `APIRequest` Application | ||
|
||
Welcome to the `APIRequest` AtomVM application. | ||
|
||
The `APIRequest` AtomVM application connects to a wifi, and when the connection is established retrieves and prints on console a GET request over https. | ||
|
||
For more information about programming on the AtomVM platform, see the [AtomVM Programmers Guide](https://www.atomvm.net/doc/master/programmers-guide.html). | ||
|
||
For general information about building and executing Elixir AtomVM example programs, see the Elixir example program [README](../README.md). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
# | ||
# This file is part of AtomVM. | ||
# | ||
# Copyright 2018 Davide Bettio <[email protected]> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You wrote this, you should give yourself credit here ;-) |
||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later | ||
# | ||
|
||
defmodule APIRequest do | ||
def start() do | ||
:io.format(~c"starting API Request application~n") | ||
UncleGrumpy marked this conversation as resolved.
Show resolved
Hide resolved
|
||
spawn(fn -> start_network() end) | ||
|
||
case wait_for_network() do | ||
:ok -> | ||
:io.format(~c"Connected to WiFi! Making HTTP request...~n") | ||
|
||
{:error, reason} -> | ||
:io.format(~c"Failed to connect to WiFi: ~p~n", [reason]) | ||
end | ||
end | ||
|
||
defp start_network() do | ||
:io.format(~c"Starting network...~n") | ||
|
||
config = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could choose to make this a demo, but if you would like to keep it as a simple example instead, I recommend using |
||
sta: [ | ||
connected: fn -> | ||
:io.format(~c"WiFi connected~n") | ||
spawn(fn -> make_request() end) | ||
end, | ||
got_ip: fn info -> :io.format(~c"Got IP: ~p~n", [info]) end, | ||
disconnected: fn -> :io.format(~c"WiFi disconnected~n") end, | ||
# Edit these values for your network: | ||
ssid: ~c"SSID_NAME", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't want hard coded credentials in the app. If someone makes a PR to update this PR in the future (maybe to accommodate AtomVM API updates) it would be easy for someone to accidentally push their credentials to GitHub. These values should be read from a config file (which a template should be provided for... I.E. config.exs-template) that should be edited by end users a renamed to the actual config file name (config.exs). The real configuration file should be added to |
||
psk: ~c"SSID_PASSWORD" | ||
] | ||
] | ||
|
||
case verify_platform(:atomvm.platform()) do | ||
:ok -> | ||
:io.format(~c"Starting network...~n") | ||
|
||
case :network.start(config) do | ||
{:ok, _pid} -> | ||
:io.format(~c"Network started.~n") | ||
# Keep the network process alive | ||
Process.sleep(:infinity) | ||
|
||
error -> | ||
error | ||
end | ||
|
||
error -> | ||
error | ||
end | ||
end | ||
|
||
defp verify_platform(:esp32), do: :ok | ||
defp verify_platform(platform), do: {:error, {:unsupported_platform, platform}} | ||
|
||
defp wait_for_network() do | ||
:io.format(~c"Waiting for network...~n") | ||
|
||
receive do | ||
{:network, :got_ip, _info} -> :ok | ||
after | ||
30_000 -> {:error, :timeout} | ||
end | ||
end | ||
|
||
defp make_request() do | ||
:io.format(~c"Making HTTPS request to api.sunrisesunset.io API...~n") | ||
|
||
ssl_opts = [{:active, false}, {:verify, :verify_none}] | ||
ok = :ssl.start() | ||
|
||
case :ahttp_client.connect(:https, ~c"api.sunrisesunset.io", 443, ssl_opts) do | ||
{:ok, conn} -> | ||
case :ahttp_client.request(conn, ~c"GET", ~c"/json?lat=38.907192&lng=-77.036873", [], nil) do | ||
{:ok, conn, ref} -> | ||
:io.format(~c"Connection established, receiving response~n") | ||
receive_response(conn, ref, []) | ||
|
||
error -> | ||
:io.format(~c"Request failed: ~p~n", [error]) | ||
end | ||
|
||
error -> | ||
:io.format(~c"Connection failed: ~p~n", [error]) | ||
end | ||
|
||
ok = :ssl.stop() | ||
end | ||
|
||
defp receive_response(conn, ref, acc) do | ||
case :ahttp_client.recv(conn, 0) do | ||
{:ok, conn, responses} -> | ||
process_responses(conn, ref, responses, acc) | ||
|
||
error -> | ||
:io.format(~c"Receive failed: ~p~n", [error]) | ||
end | ||
end | ||
|
||
defp process_responses(conn, ref, [], acc) do | ||
:ahttp_client.close(conn) | ||
|
||
case acc do | ||
[data | _] -> | ||
:io.format(~c"Data: ~p~n", [data]) | ||
|
||
_ -> | ||
:ok | ||
end | ||
end | ||
|
||
defp process_responses(conn, ref, [{:status, ref, status} | rest], acc) do | ||
:io.format(~c"Status: ~p~n", [status]) | ||
process_responses(conn, ref, rest, acc) | ||
end | ||
|
||
defp process_responses(conn, ref, [{:header, ref, {name, value}} | rest], acc) do | ||
:io.format(~c"Header: ~s: ~s~n", [name, value]) | ||
process_responses(conn, ref, rest, acc) | ||
end | ||
|
||
defp process_responses(conn, ref, [{:data, ref, data} | rest], acc) do | ||
process_responses(conn, ref, rest, [data | acc]) | ||
end | ||
|
||
defp process_responses(conn, ref, [{:done, ref} | rest], acc) do | ||
process_responses(conn, ref, rest, acc) | ||
end | ||
|
||
defp process_responses(conn, ref, [_response | rest], acc) do | ||
process_responses(conn, ref, rest, acc) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
defmodule APIRequest.MixProject do | ||
use Mix.Project | ||
|
||
def project do | ||
[ | ||
app: :APIRequest, | ||
version: "0.1.0", | ||
elixir: "~> 1.13", | ||
start_permanent: Mix.env() == :prod, | ||
deps: deps(), | ||
atomvm: [ | ||
start: APIRequest, | ||
flash_offset: 0x250000 | ||
] | ||
] | ||
end | ||
|
||
# Run "mix help compile.app" to learn about applications. | ||
def application do | ||
[ | ||
extra_applications: [:logger] | ||
] | ||
end | ||
|
||
# Run "mix help deps" to learn about dependencies. | ||
defp deps do | ||
[ | ||
{:exatomvm, git: "https://github.com/atomvm/ExAtomVM/"} | ||
] | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ defmodule Blinky.MixProject do | |
deps: deps(), | ||
atomvm: [ | ||
start: Blinky, | ||
flash_offset: 0x210000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should make this correction in a separate PR. |
||
flash_offset: 0x250000 | ||
] | ||
] | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ defmodule HelloWorld.MixProject do | |
deps: deps(), | ||
atomvm: [ | ||
start: HelloWorld, | ||
flash_offset: 0x210000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be in a separate PR (it can be together with the above correction) we just want to keep the new additions in a different commit from the corrections to other examples. It makes the commit log cleaner and more useful. |
||
flash_offset: 0x250000 | ||
] | ||
] | ||
end | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could change this to "...is established makes a GET request over https and prints the result to the console." Reading this I half expected the ESP32 to be the server getting the API request from a client, and printing the actual request on a the console.
That would be a strange example, but there were enough details left out to make it hard to be certain which details were missing, especially for non-native English speakers. ;-)