Skip to content

Instantly share code, notes, and snippets.

@robinchew
Last active February 22, 2025 03:49
Show Gist options
  • Save robinchew/94d1b134a4b2a026d1bdfae3551c5520 to your computer and use it in GitHub Desktop.
Save robinchew/94d1b134a4b2a026d1bdfae3551c5520 to your computer and use it in GitHub Desktop.
-module(gas_sensor_atomvm).
-export([
start/0,
init_handler/2,
handle_http_req/2,
handle_ws_init/3,
handle_ws_message/2,
poll_server1/3
]).
-record(state, {
path_suffix,
handler_config
}).
-include_lib("config.hrl").
-define(COMMON_HEADERS, #{"Content-Type" => "text/plain", "Access-Control-Allow-Origin" => "*"}).
poll_server1(SensorDataServerPid, ProcPrinter, {Socket, Pid}) ->
receive
{remove_client, Socket} ->
Pid ! stop_poll_server_client,
poll_server1(SensorDataServerPid, ProcPrinter, no_client);
UnexpectedMessage ->
io:format("poll_server received an unexpected message ~p~n", [UnexpectedMessage])
end;
poll_server1(SensorDataServerPid, ProcPrinter, no_client) ->
PollRate = 3000,
receive
{new_client, NewSocket} ->
NewEventPid = spawn(fun Repeat() ->
spawn_link(fun() ->
Data1 = <<"2,2025-02-21T15:32:31,22,46,18,23,5,2023,0,28702,24461,65528,11692,8758,1574,6,6,6,0,29,6,56881,0
1,2025-02-21T15:32:31,16,54,1,23,5,2023,0,29931,21314,35152,30298,2981,2101,510,2872,45,4171,155,16,46034,1
3,2025-02-21T15:32:32,13,38,17,23,5,2023,0,30564,19755,33257,13510,2983,2984,473,2506,300,5014,297,16,47230,1">>,
httpd_ws_handler:send(NewSocket, Data1)
end),
receive
stop_poll_server_client -> end_process
after PollRate -> Repeat()
end
end),
poll_server1(SensorDataServerPid, ProcPrinter, {NewSocket, NewEventPid});
_ -> blah
end.
start() ->
ssl:start(),
Self = self(),
Config = [
{sta, [
{ssid, ?WIFI_SSID},
{psk, ?WIFI_PASSWORD},
{connected, fun() -> Self ! connected end},
{got_ip, fun(IpInfo) -> Self ! {ok, IpInfo} end},
{disconnected, fun() -> Self ! disconnected end}
]}
],
case network:start(Config) of
{ok, Pid} ->
io:format("Network Started ~p~n", [Pid]),
wait_for_message([]);
Error ->
io:format("An error occurred starting network: ~p~n", [Error])
end.
wait_for_message(_Messages) ->
continue = (fun
Loop(#{ip_acquired := _}) ->
continue;
Loop(Map) ->
Loop(receive
connected ->
Map;
{ok, IpInfo} ->
io:format("Acquired IP address: ~p~n", [IpInfo]),
Map#{ip_acquired => IpInfo};
ntp_synced ->
io:format("NTP Synced~n"),
Map#{ntp_synced => true};
disconnected ->
Map
after 15000 ->
Map
end)
end)(#{}),
spawn_link(fun Loop() ->
Pids = erlang:processes(),
io:format("FREE HEAP SIZE: ~p (~p processes)~n", [erlang:system_info(esp32_free_heap_size), length(Pids)]),
% lists:foreach(
% fun(Pid) ->
% {_, Mem, _} = just_log_pid(Pid),
% io:format("~p ~p~n", [Pid, Mem])
% end,
% Pids),
timer:sleep(5000),
Loop()
end),
PollServer = spawn_link(fun() ->
io:format("poll_server ~p~n", [self()]),
poll_server1(null, null, no_client)
end),
httpd:start_link(80, [
{[<<"events">>], #{
handler => httpd_ws_handler,
handler_config => #{
module => ?MODULE,
args => [
{poll_server, PollServer}
]
}
}},
{[], #{
handler => ?MODULE
}}
]),
(fun InfiniteLoop() ->
receive
Msg ->
io:format("Got ~p. But still blocking forever.~n", [Msg]),
InfiniteLoop()
end
end)().
init_handler(PathSuffix, HandlerConfig) ->
{ok, #state{
path_suffix = PathSuffix,
handler_config = HandlerConfig
}}.
handle_http_req(_Request, _State) ->
{close, ?COMMON_HEADERS#{"Content-Type" => "text/html"}, <<"
<script>
const eventSource = new window.WebSocket('/events');
eventSource.onopen = (e) => {
console.log('ws open', e);
};
eventSource.onmessage = ({ data }) => {
if (data === 'close') {
eventSource.close();
return;
}
if (data === 'pong') {
return;
}
};
setInterval(
() => {
eventSource.send('ping');
},
10000);
</script>
">>}.
% WEBSOCKET
handle_ws_init(WebSocket, _Path = "", Conn) ->
PollServer = proplists:get_value(poll_server, Conn),
WsInnerSpawn = spawn_link(fun() ->
io:format("WebSocket init PID ~p -> ~p~n", [WebSocket, self()]),
timer:sleep(2000),
PollServer ! {new_client, WebSocket}
end),
{ok, {inner_spawn, WsInnerSpawn}}.
handle_ws_message(<<"ping">>, State) ->
{reply, <<"pong">>, State};
handle_ws_message(Message, State) ->
io:format("Received message from web socket. Message: ~p~n", [Message]),
{noreply, State}.
@robinchew
Copy link
Author

@robinchew
Copy link
Author

Remember to set in config.hrl:

-define(WIFI_SSID, "MY_SSID").
-define(WIFI_PASSWORD, "mypassword123").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment