Skip to content
This repository was archived by the owner on Sep 22, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions config/sys.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[
{rolnik, [
{lower_limit, 5},
{upper_limit, 30},
{temp_check_freq, 1000},
{checks_per_sample, 60},
{normal_status_return_limit, 0.5},
{smtp_config, [
{relay, {192,168,0,111}},
{ssl, true},
{username, "login@mail.com"},
{password, "mailpassword"}
]},
{alarm_sender_email, "login@mail.com"},
{alarm_receiver_email, "receiveremail@mail.com"}
]}
].
28 changes: 28 additions & 0 deletions config/test.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[
{rolnik, [
{lower_limit, 5},
{upper_limit, 30},
{temp_check_freq, 1000},
{checks_per_sample, 60},
{normal_status_return_limit, 0.5},
{smtp_config, [
{relay, {192,168,0,111}},
{ssl, true},
{username, "login@mail.com"},
{password, "mailpassword"}
]},
{alarm_sender_email, "login@mail.com"},
{alarm_receiver_email, "receiveremail@mail.com"}
]},
{grisp, [
{drivers, [
{spi, grisp_spi_drv_emu},
{gpio, grisp_gpio_drv_emu},
{i2c, grisp_i2c_drv_emu}
]},
{devices, [
{spi1, pmod_nav},
{spi2, pmod_gyro}
]}
]}
].
11 changes: 11 additions & 0 deletions grisp/grisp_base/files/erl_inetrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
% Add hosts
{host, {192,168,0,32}, ["yourpc-name"]}.

% Do not monitor the hosts file
{hosts_file, ""}.

% Disable caching
{cache_size, 0}.

% Specify lookup method
{lookup, [file, native]}.
11 changes: 11 additions & 0 deletions grisp/grisp_base/files/grisp.ini.mustache
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[boot]
image_path = /media/mmcsd-0-0/{{release_name}}/erts-{{erts_vsn}}/bin/beam.bin

[erlang]
args = erl.rtems -- -home . -pa . -root {{release_name}} -boot {{release_name}}/releases/{{release_version}}/{{release_name}} -internal_epmd epmd_sup -kernel inetrc "./erl_inetrc" -sname {{release_name}} -setcookie test -config {{release_name}}/releases/{{release_version}}/sys.config

[network]
ip_self = dhcp
wlan = enable
hostname = grisp
wpa = wpa_supplicant.conf
5 changes: 5 additions & 0 deletions grisp/grisp_base/files/wpa_supplicant.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
network={
ssid="network_name"
key_mgmt=WPA-PSK
psk="password"
}
27 changes: 23 additions & 4 deletions rebar.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{deps, [grisp]}.
{deps, [
{grisp, {git, "git://github.com/grisp/grisp.git"}},
{epmd, {git, "https://github.com/erlang/epmd", {ref, "4d1a59"}}},
{gen_smtp, ".*", {git, "https://github.com/Vagabond/gen_smtp.git", "master"}}
]}.

{erl_opts, [debug_info]}.

Expand All @@ -7,15 +11,30 @@
{version, "20.2"}
]},
{deploy, [
{destination, "/tmp/sd_card"}
{pre_script, "rm -rf /run/media/seb/GRISP/*"},
{destination, "/run/media/seb/GRISP"},
{post_script, "umount /run/media/seb/GRISP"}
]},
{toolchain, [
{root, "/Users/michalslaski/dev/GRiSP/grisp-software/rtems-install/rtems-4.12"}
{root, "/home/seb/GRiSP/grisp-software/rtems-install/rtems-4.12"}
]}
]}.

{shell, [{apps, []}]}.

{relx, [
{release, {rolnik, "0.1.0"}, [rolnik]}
{release,
{rolnik, "0.1.0"},
[{epmd, none}, gen_smtp, rolnik],
[{sys_config, "./config/sys.config"}]}
]}.


{profiles, [
{test, [
{shell, [{apps, [rolnik]},
{config, "config/test.config"}
]}
]}
]}.

18 changes: 18 additions & 0 deletions rebar.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{"1.1.0",
[{<<"epmd">>,
{git,"https://github.com/erlang/epmd",
{ref,"4d1a595b9d5c32fc0e55f462da381de62de23bf0"}},
0},
{<<"gen_smtp">>,
{git,"https://github.com/Vagabond/gen_smtp.git",
{ref,"e07022695735fe3b3eaf0fca52d85e91eef2a67f"}},
0},
{<<"grisp">>,
{git,"git://github.com/grisp/grisp.git",
{ref,"23860074abb8de6c77cee5a11e1a5b2685060260"}},
0},
{<<"mapz">>,{pkg,<<"mapz">>,<<"0.3.0">>},1}]}.
[
{pkg_hash,[
{<<"mapz">>, <<"438D24746CE5A252101E00B2032EFDF7FC69EB32689D3B805DE5E6DD7F52614F">>}]}
].
1 change: 1 addition & 0 deletions src/rolnik.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
{applications, [
kernel,
stdlib,
gen_smtp,
grisp
]},
{env,[]},
Expand Down
66 changes: 66 additions & 0 deletions src/rolnik_notifier.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
%% @doc
%% @end
-module(rolnik_notifier).

-behaviour(gen_server).

%% API
-export([start_link/1, alarm/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, terminate/2, code_change/3]).

-record(state, {socket_info, sender_email, receiver_email}).

%% API

%% @doc Starts rolnik_notifier which handles sending alarm messages to client
%% when temperature status changes from normal
-spec start_link(Args :: list()) -> {ok, pid()} | ignore | {error, term()}.
start_link(Args)->
gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).

%% @doc Starts rolnik_notifier which handles sending alarm messages to client
-spec alarm(Status :: atom()) -> ok.
alarm(Status) ->
gen_server:call(?MODULE, {alarm, Status}).

%% gen_server callbacks

init([SmtpConfig, Sender, Receiver]) ->
process_flag(trap_exit, true),
SocketInfo = open_socket_for_notify(SmtpConfig),
{ok, #state{socket_info = SocketInfo, sender_email = Sender,
receiver_email = Receiver}}.

handle_call({alarm, below}, _From, State) ->
Message = "Subject: Temperature Warning\r\nFrom: GRISP board \r\n
Temperature dropped below the lower limit.",
send(Message, State),
{reply, ok, State};
handle_call({alarm, above}, _From, State) ->
Message = "Subject: Temperature Warning\r\nFrom: GRISP board \r\n
Temperature rised above the upper limit.",
send(Message, State),
{reply, ok, State}.

handle_cast(_Msg, State) ->
{noreply, State}.

terminate(_Reason, _State) ->
ok.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.

%% Internal functions

open_socket_for_notify(SmtpConfig) ->
{ok, SocketInfo} = gen_smtp_client:open(SmtpConfig),
SocketInfo.

send(Message, #state{socket_info = SocketInfo, sender_email = Sender,
receiver_email = Receiver}) ->
% Info backup to implement
{ok, _Info} = gen_smtp_client:deliver(SocketInfo, {Sender, [Receiver],
Message}).
56 changes: 53 additions & 3 deletions src/rolnik_sup.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,59 @@
-export([init/1]).

%--- API -----------------------------------------------------------------------

start_link() -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%% @doc Starts rolnik top level supervisor.
-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
{ok, Pid} = supervisor:start_link({local, ?MODULE}, ?MODULE, []),
%% start event handlers
{ok, LowerLimit} = application:get_env(rolnik, lower_limit),
{ok, UpperLimit} = application:get_env(rolnik, upper_limit),
{ok, ChecksPerSample} = application:get_env(rolnik, checks_per_sample),
{ok, StatusReturnLimit} = application:get_env(rolnik, normal_status_return_limit),
ok = gen_event:add_handler(rolnik_temp_notify_manager,
rolnik_temp_limit_handler,
[LowerLimit, UpperLimit, ChecksPerSample,
StatusReturnLimit]),
ok = gen_event:add_handler(rolnik_temp_notify_manager,
rolnik_temp_backup_handler, []),
{ok, Pid}.

%--- Callbacks -----------------------------------------------------------------

init([]) -> {ok, { {one_for_all, 0, 1}, []} }.
init([]) ->
{ok, SmtpConfig} = application:get_env(rolnik, smtp_config),
{ok, Sender} = application:get_env(rolnik, alarm_sender_email),
{ok, Receiver} = application:get_env(rolnik, alarm_receiver_email),
{ok, TempCheckFreq} = application:get_env(rolnik, temp_check_freq),
SensorId = get_sensor_id(),
SupFlags = #{strategy => one_for_one, intensity => 1, period => 5},
ChildSpecs = [
%% start rolnik_notifier
#{id => rolnik_notifier_id,
start => {rolnik_notifier, start_link, [[SmtpConfig,
Sender, Receiver]]},
restart => permanent,
shutdown => brutal_kill,
type => worker,
modules => [rolnik_notifier]},
%% start event manager
{rolnik_temp_notify_manager, {gen_event, start_link,
[{local, rolnik_temp_notify_manager}]},
permanent, 5000, worker, [dynamic]},
%% start rolnik_temp_checker
#{id => rolnik_temp_checker_id,
start => {rolnik_temp_checker, start_link, [[TempCheckFreq,
SensorId]]},
restart => permanent,
shutdown => brutal_kill,
type => worker,
modules => [rolnik_temp_checker]}
],
{ok, {SupFlags, ChildSpecs}}.

%% Internal functions

get_sensor_id() ->
[ID] = grisp_onewire:transaction(fun() -> grisp_onewire:search() end),
ID.

29 changes: 29 additions & 0 deletions src/rolnik_temp_backup_handler.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
-module(rolnik_temp_backup_handler).
-behaviour(gen_event).

-export([init/1, handle_event/2, handle_call/2, handle_info/2, code_change/3,
terminate/2]).

-record(state, {temps = []}).

init([]) ->
{ok, #state{}}.

handle_event(TimeTempData, #state{temps = TempsBackup}) ->
UpdatedTempsBackup = [TimeTempData | TempsBackup],
NewState = #state{temps = UpdatedTempsBackup},
{ok, NewState}.

handle_call(_, State) ->
{ok, ok, State}.

handle_info(_, State) ->
{ok, State}.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.

terminate(_Reason, _State) ->
ok.

%% Internal functions
69 changes: 69 additions & 0 deletions src/rolnik_temp_checker.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
%% @doc
%% @end
-module(rolnik_temp_checker).

-behaviour(gen_server).

%% API
-export([start_link/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).

-record(state, {temp_check_freq, sensor_id}).

%% API

%% @doc Starts rolnik_temp_checker which notifies rolnik_temp_notify_manager
%% about temperature with given frequency
-spec start_link(Args :: list()) -> {ok, pid()} | ignore | {error, term()}.
start_link(Args) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).

%% gen_server callbacks

init([TempCheckFreq, SensorId]) ->
process_flag(trap_exit, true),
%% Request first update after giving time for whole app to start
?MODULE ! temp_update,
ok = led_start_notify(),
{ok, #state{temp_check_freq = TempCheckFreq, sensor_id = SensorId}}.

handle_call(_Msg, _From, State) ->
{reply, ok, State}.

handle_cast(_Msg, State) ->
{noreply, State}.

handle_info(temp_update, State = #state{temp_check_freq = Lag, sensor_id = Id}) ->
ok = request_temp_update_after_lag(Lag),
{ok, NewTemp} = get_temp(Id),
ok = temp_notify(NewTemp),
{noreply, State}.

terminate(_Reason, _State) ->
ok.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.

%% Internal functions
led_start_notify() ->
grisp_led:color(1, aqua),
ok.

request_temp_update_after_lag(Lag) ->
erlang:send_after(Lag, ?MODULE, temp_update),
ok.

get_temp(Id) ->
ok = onewire_ds18b20:convert(Id, 500),
Temp = onewire_ds18b20:temp(Id),
{ok, Temp}.

temp_notify(Temp) ->
Time = erlang:localtime(),
TimeTempData = {Time, Temp},
gen_event:notify(rolnik_temp_notify_manager, TimeTempData),
ok.
Loading