Browse Source

Removed ~n control sequences which cause a crash due to io_lib:format not handling ~n correctly only sometimes.

master
Ruel Tmeizeh - RuhNet 2 years ago
parent
commit
216ca7df1c
10 changed files with 105 additions and 107 deletions
  1. +10
    -10
      src/button_watcher.erl
  2. +20
    -20
      src/control.erl
  3. +4
    -4
      src/debugger.erl
  4. +6
    -6
      src/led.erl
  5. +28
    -28
      src/mqtt.erl
  6. +1
    -1
      src/network_sup.erl
  7. +12
    -12
      src/temperature.erl
  8. +5
    -5
      src/thermostat.erl
  9. +7
    -9
      src/util.erl
  10. +12
    -12
      src/wifi.erl

+ 10
- 10
src/button_watcher.erl View File

@ -12,12 +12,12 @@
-export([start_link/0, init/1]).
start_link() ->
io:format("Starting '~p' with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting '~p' with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
init([]).
%timer:sleep(1).
init(_) ->
io:format("[~p:~p] Starting...~n", [?MODULE, ?FUNCTION_NAME]),
debugger:format("[~p:~p] Starting...", [?MODULE, ?FUNCTION_NAME]),
led:flash(?STATUS_LED, 20, 20),
%_Pid = spawn_link(?MODULE, read_buttons, []),
%{ok, self()}.
@ -28,30 +28,30 @@ read_buttons() ->
case gpio:digital_read(?BUTTON_MODE) of
low ->
control:cycle_mode(),
io:format("[~p:~p] Mode button (~p) pressed!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_MODE]);
io:format("[~p:~p] Mode button (~p) pressed!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_MODE]);
high ->
io:format("[~p:~p] Mode button (~p) released!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_MODE])
io:format("[~p:~p] Mode button (~p) released!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_MODE])
end,
case gpio:digital_read(?BUTTON_FAN) of
low ->
control:cycle_fan(),
io:format("[~p:~p] Fan button (~p) pressed!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_FAN]);
io:format("[~p:~p] Fan button (~p) pressed!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_FAN]);
high ->
io:format("[~p:~p] Fan button (~p) released!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_FAN])
io:format("[~p:~p] Fan button (~p) released!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_FAN])
end,
case gpio:digital_read(?BUTTON_TEMP_UP) of
low ->
thermostat:up(),
io:format("[~p:~p] Temp up button (~p) pressed!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_UP]);
io:format("[~p:~p] Temp up button (~p) pressed!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_UP]);
high ->
io:format("[~p:~p] Temp up button (~p) released!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_UP])
io:format("[~p:~p] Temp up button (~p) released!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_UP])
end,
case gpio:digital_read(?BUTTON_TEMP_DOWN) of
low ->
thermostat:down(),
io:format("[~p:~p] Temp down button (~p) pressed!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_DOWN]);
io:format("[~p:~p] Temp down button (~p) pressed!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_DOWN]);
high ->
io:format("[~p:~p] Temp down button (~p) released!~n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_DOWN])
io:format("[~p:~p] Temp down button (~p) released!\n", [?MODULE, ?FUNCTION_NAME, ?BUTTON_TEMP_DOWN])
end,
timer:sleep(50),
read_buttons().


+ 20
- 20
src/control.erl View File

@ -26,11 +26,11 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
start_link() ->
debugger:format("Starting '~p' with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting '~p' with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
{ok, _Pid} = gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init(_) ->
debugger:format("Starting '~p' with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting '~p' with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
util:beep(880, 1000),
%erlang:send_after(200, self(), start),
erlang:send_after(200, ?MODULE, start),
@ -41,7 +41,7 @@ terminate(_Reason, _State) ->
ok.
handle_cast(set_safe, _State=[{mode, M}, {fan, F}, {compressor, C}, {compressor_safe, _CS}]) ->
debugger:format("[~p:~p] overriding wait timer; setting compressor_safety: 'safe'~n", [?MODULE, ?FUNCTION_NAME]),
debugger:format("[~p:~p] overriding wait timer; setting compressor_safety: 'safe'", [?MODULE, ?FUNCTION_NAME]),
spawn(fun() -> led:flash(?COMPRESSOR_LED, 50, 8) end),
{noreply, [{mode, M}, {fan, F}, {compressor, C}, {compressor_safe, safe}] };
@ -83,7 +83,7 @@ handle_call({set_fan, FanNew}, _From, _State=[{mode, Mode}, {fan, F}, {compresso
{reply, ok, [{mode, Mode}, {fan, F}, {compressor, C}, {compressor_safe, CS}] };
handle_call(Msg, _From, State) ->
debugger:format("[~p] Received unknown ~p message: ~p~n", [?MODULE, ?FUNCTION_NAME, Msg]),
debugger:format("[~p] Received unknown ~p message: ~p", [?MODULE, ?FUNCTION_NAME, Msg]),
{reply, ok, State}.
@ -91,22 +91,22 @@ handle_info(start, State) ->
% Start first compressor safety timer
erlang:send(?MODULE, operation_loop),
%[{mode, M}, {fan, F}, {compressor, C}, {compressor_safe, CS}] = State,
%debugger:format("[control] handle_info start: State=[mode:~p f:~p comp:~p cs:~p].~n", [M, F, C, CS]),
debugger:format("[~p:~p]start Setting initial safety delay of ~p seconds...~n", [?MODULE, ?FUNCTION_NAME, trunc(?SAFETY_DELAY / 1000)]),
%debugger:format("[control] handle_info start: State=[mode:~p f:~p comp:~p cs:~p].", [M, F, C, CS]),
debugger:format("[~p:~p]start Setting initial safety delay of ~p seconds...", [?MODULE, ?FUNCTION_NAME, trunc(?SAFETY_DELAY / 1000)]),
fan(0), %just in case we crashed and fan is still on.
compressor_set(off), %just in case we crashed and compressor is still on.
erlang:send_after(?SAFETY_DELAY, ?MODULE, {compressor_safety, safe}), %mark safe after the delay has elapsed
{noreply, State};
handle_info({compressor_safety, CSafe}, _State=[{mode, M}, {fan, F}, {compressor, C}, {compressor_safe, _CS}]) ->
debugger:format("[~p:~p] setting compressor_safety to: ~p~n", [?MODULE, ?FUNCTION_NAME, CSafe]),
%io:format("[control] handle_info compressorsafety:~p. State=[mode:~p f:~p comp:~p cs:~p].~n", [CSafe, M, F, C, _CS]),
%io:format("[control] handle_info compressorsafety NewState=[mode:~p f:~p comp:~p cs:~p].~n", [M, F, C, CSafe]),
debugger:format("[~p:~p] setting compressor_safety to: ~p", [?MODULE, ?FUNCTION_NAME, CSafe]),
%io:format("[control] handle_info compressorsafety:~p. State=[mode:~p f:~p comp:~p cs:~p].", [CSafe, M, F, C, _CS]),
%io:format("[control] handle_info compressorsafety NewState=[mode:~p f:~p comp:~p cs:~p].", [M, F, C, CSafe]),
{noreply, [{mode, M}, {fan, F}, {compressor, C}, {compressor_safe, CSafe}] };
%%% MODE SELECTION off|cool|energy_saver|fan_only
handle_info({set_mode, Mode}, _State=[{mode, M}, {fan, F}, {compressor, C}, {compressor_safe, CS}]) ->
debugger:format("[~p:~p] changing mode from ~p to new setting: ~p~n", [?MODULE, ?FUNCTION_NAME, M, Mode]),
debugger:format("[~p:~p] changing mode from ~p to new setting: ~p", [?MODULE, ?FUNCTION_NAME, M, Mode]),
{Comp, CSafe} = case Mode of
off ->
fan(0),
@ -162,7 +162,7 @@ handle_info({set_fan, FanNew}, _State=[{mode, Mode}, {fan, FanPrev}, {compressor
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%compressor not safe (wait)
handle_info(operation_loop, State=[{mode, Mode}, {fan, F}, {compressor, C}, {compressor_safe, wait}]) ->
debugger:format("[~p:~p] operation_loop State=[mode:~p f:~p comp:~p cs:wait].~n", [?MODULE, ?FUNCTION_NAME, Mode, F, C]),
debugger:format("[~p:~p] operation_loop State=[mode:~p f:~p comp:~p cs:wait].", [?MODULE, ?FUNCTION_NAME, Mode, F, C]),
case C of
on -> compressor_set(off); %this should never happen, but if it does, we want the log message
_ -> compressor_set_outputs(off) %silently make sure compressor is off
@ -170,7 +170,7 @@ handle_info(operation_loop, State=[{mode, Mode}, {fan, F}, {compressor, C}, {com
case Mode of %allow fan to run even if compressor is in 'wait' stage
cool -> fan(F);
energy_saver ->
debugger:format("[~p] Turning fan off since we are in energy_saver mode and compressor is off...~n", [?MODULE]),
debugger:format("[~p] Turning fan off since we are in energy_saver mode and compressor is off...", [?MODULE]),
fan(0);
fan_only -> fan_on(F);
_ -> ok
@ -208,7 +208,7 @@ handle_info(operation_loop, [{mode, Mode}, {fan, F}, {compressor, off}, {compres
true -> off
end,
State = [{mode, Mode}, {fan, F}, {compressor, Comp}, {compressor_safe, safe}],
debugger:format("[~p:~p] operation_loop State=[mode:~p f:~p comp:~p cs:~p].~n", [?MODULE, ?FUNCTION_NAME, Mode, F, Comp, safe]),
debugger:format("[~p:~p] operation_loop State=[mode:~p f:~p comp:~p cs:~p].", [?MODULE, ?FUNCTION_NAME, Mode, F, Comp, safe]),
notify(?TOPIC_STATUS, status_binary(State)),
erlang:send_after(20000, ?MODULE, operation_loop),
{noreply, State};
@ -228,7 +228,7 @@ handle_info(operation_loop, [{mode, Mode}, {fan, F}, {compressor, on}, {compress
erlang:send_after(?SAFETY_DELAY, ?MODULE, {compressor_safety, safe}),
Msg = io_lib:format("COMPRESSOR FREEZE STOP! Coil temperature is: ~.1f", [CoilTemp]),
spawn(fun() -> util:beep(880, 1000), util:beep(440, 1000), util:beep(880, 1000), util:beep(880, 1000) end),
debugger:format("~p~n", [Msg]),
debugger:format("~p", [Msg]),
{off, wait, Msg};
%Temp =< (TSet - HalfSpan) -> %normal temp low compressor shutoff
TempIsLow -> %normal temp low compressor shutoff
@ -240,8 +240,8 @@ handle_info(operation_loop, [{mode, Mode}, {fan, F}, {compressor, on}, {compress
{on, safe, "ok"}
end,
State = [{mode, Mode}, {fan, F}, {compressor, Comp}, {compressor_safe, CS}],
%debugger:format("[~p] ~p operation_loop T=~.2f, CT=~.2f, TS=~p, S=~.1f, State=[mode:~p f:~p comp:~p cs:~p].~n", [?MODULE, ?FUNCTION_NAME, Temp, CoilTemp,TSet, Span, Mode, F, on, safe]),
debugger:format("[~p:~p] operation_loop State=[mode:~p f:~p comp:~p cs:~p].~n", [?MODULE, ?FUNCTION_NAME, Mode, F, Comp, CS]),
%debugger:format("[~p] ~p operation_loop T=~.2f, CT=~.2f, TS=~p, S=~.1f, State=[mode:~p f:~p comp:~p cs:~p].", [?MODULE, ?FUNCTION_NAME, Temp, CoilTemp,TSet, Span, Mode, F, on, safe]),
debugger:format("[~p:~p] operation_loop State=[mode:~p f:~p comp:~p cs:~p].", [?MODULE, ?FUNCTION_NAME, Mode, F, Comp, CS]),
notify(?TOPIC_STATUS, status_binary(State, StatusMsg)),
erlang:send_after(20000, ?MODULE, operation_loop),
{noreply, State}.
@ -330,7 +330,7 @@ cutoff_check(Temp, TSet, Span) ->
true -> TSet - HalfSpan;
_ -> TSet - LargePartOfSpan
end,
debugger:format("[~p:~p] Cutoff Temps: [highpoint: ~.2f lowpoint: ~.2f]~n", [?MODULE, ?FUNCTION_NAME, HighPoint, LowPoint]),
debugger:format("[~p:~p] Cutoff Temps: [highpoint: ~.2f lowpoint: ~.2f]", [?MODULE, ?FUNCTION_NAME, HighPoint, LowPoint]),
{Temp >= HighPoint, Temp =< LowPoint}.
@ -345,7 +345,7 @@ all_off() ->
fan(0).
compressor_set(C) ->
debugger:format("[~p] ~p: TURNING ~p COMPRESSOR.~n", [?MODULE, ?FUNCTION_NAME, C]),
debugger:format("[~p] ~p: TURNING ~p COMPRESSOR.", [?MODULE, ?FUNCTION_NAME, C]),
compressor_set_outputs(C).
compressor_set_outputs(C) ->
@ -360,7 +360,7 @@ fan_on(F) ->
end.
fan(F) ->
debugger:format("Setting fan to ~p.~n", [F]),
debugger:format("Setting fan to ~p.", [F]),
case util:make_int(F) of
0 ->
util:set_output(?FAN1, off),
@ -390,7 +390,7 @@ fan(F) ->
notify(Topic, Msg) ->
case whereis(mqtt_client) of
undefined -> io:format("MQTT is not alive; message: ~p~n", [Msg]);
undefined -> io:format("MQTT is not alive; message: ~p", [Msg]);
%_Pid -> spawn( fun() -> mqtt:pub(Topic, Msg) end) % this notify/2 is called from handle_call/handle_info, so need to return quickly.
_Pid -> mqtt:publish_and_forget(Topic, Msg) % this notify/2 is called from handle_call/handle_info, so need to return quickly.
end.


+ 4
- 4
src/debugger.erl View File

@ -50,13 +50,13 @@ handle_cast(Msg, State={DebugType, _}) ->
%handle_info(time, State) ->
% {{Year, Month, Day}, {Hour, Minute, Second}} = erlang:universaltime(),
% debugger:format("[DEBUG] Time: ~p/~2..0p/~2..0p ~2..0p:~2..0p:~2..0p ~n", [ Year, Month, Day, Hour, Minute, Second ]),
% debugger:format("[DEBUG] Time: ~p/~2..0p/~2..0p ~2..0p:~2..0p:~2..0p", [ Year, Month, Day, Hour, Minute, Second ]),
% erlang:send_after(60000, self(), time),
% {noreply, State};
handle_info(uptime, State) ->
{_, {{Year, Month, Day}, {Hour, Minute, Second}}} = State,
debugger:format("BOOT TIME: ~p/~2..0p/~2..0p ~2..0p:~2..0p:~2..0p ~n", [ Year, Month, Day, Hour, Minute, Second ]),
debugger:format("UPTIME: ~p minutes ~n", [trunc(erlang:monotonic_time(second)/60)]),
debugger:format("BOOT TIME: ~p/~2..0p/~2..0p ~2..0p:~2..0p:~2..0p", [ Year, Month, Day, Hour, Minute, Second ]),
debugger:format("UPTIME: ~p minutes ", [trunc(erlang:monotonic_time(second)/60)]),
%erlang:send_after(900000, self(), uptime), %repeat every 15 minutes
{noreply, State};
handle_info(Msg, State) ->
@ -69,7 +69,7 @@ terminate(_Reason, _State) ->
select_output(Mode, Msg) ->
case Mode of
console_only ->
%io:format("[DEBUG]: ~p~n", [Msg]);
%io:format("[DEBUG]: ~p\n", [Msg]);
io:format(Msg),
io:format("\n");
mqtt_only ->


+ 6
- 6
src/led.erl View File

@ -15,12 +15,12 @@
%-export([start_link/0, init/1, handle_call/3, handle_cast/2, terminate/2]).
%
%start_link() ->
% io:format("Starting '~p' with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
% io:format("Starting '~p' with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
% {ok, _Pid} = gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
% %timer:sleep(1).
%
%init(_) ->
% io:format("[~p:~p] Starting...~n", [?MODULE, ?FUNCTION_NAME]),
% io:format("[~p:~p] Starting...", [?MODULE, ?FUNCTION_NAME]),
% flash_led(?STATUS_LED, 50, 20),
% util:set_output(?STATUS_LED, on),
% {ok, []}.
@ -32,10 +32,10 @@
% %{reply, ok, [Pid|State]};
% {reply, ok, State};
%handle_call(listproc, _From, State) ->
% io:format("Processes: ~p ~n", [State]),
% io:format("Processes: ~p ", [State]),
% {reply, ok, State};
%handle_call(reset, _From, State) ->
% io:format("Processes: ~p ~n", [State]),
% io:format("Processes: ~p ", [State]),
% kill_flashers(State),
% {reply, ok, []};
%handle_call(Call, _From, State) ->
@ -69,11 +69,11 @@ flash(Pin) ->
flash_led(Pin, 1000, forever).
% gen_server:call(?MODULE, {flash, Pin, 1000, forever}).
flash(Pin, Interval) ->
io:format("Flashing Pin ~p FOREVER with interval ~p ms.~n", [Pin, Interval]),
debugger:format("Flashing Pin ~p FOREVER with interval ~p ms.", [Pin, Interval]),
flash_led(Pin, Interval, forever).
% gen_server:call(?MODULE, {flash, Pin, Interval, forever}).
flash(Pin, Interval, Times) ->
io:format("Flashing Pin ~p ~p times with interval ~p ms.~n", [Pin, Times, Interval]),
debugger:format("Flashing Pin ~p ~p times with interval ~p ms.", [Pin, Times, Interval]),
flash_led(Pin, Interval, Times).
% gen_server:call(?MODULE, {flash, Pin, Interval, Times}).


+ 28
- 28
src/mqtt.erl View File

@ -15,12 +15,12 @@
-include("app.hrl").
start_link() ->
io:format("Starting '~p' with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting '~p' with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
{ok, _Pid} = gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
%{ok, _Pid} = init([]).
init(_) ->
io:format("Starting '~p' with ~p/~p...~n", [mqtt_client, start_link, 1]),
debugger:format("Starting '~p' with ~p/~p...", [mqtt_client, start_link, 1]),
%{ok, {no_mqtt_pid, not_ready}}.
My_Pid = self(),
{ok, {My_Pid, not_ready}}.
@ -31,15 +31,15 @@ start_mqtt_client() ->
MQTTConfig = #{
url => maps:get(url, Config),
client_id => ?DEVICENAME,
disconnected_handler => fun(_MQTT_CLIENT_PID) -> io:format("DISCONNECTED from MQTT!!!!!!~n"), mqtt_client:reconnect(whereis(mqtt_client)) end,
error_handler => fun(_MQTT_CLIENT_PID, Err) -> io:format("[~p:~p] ~p~n", [?MODULE, ?FUNCTION_NAME, Err]) end,
disconnected_handler => fun(_MQTT_CLIENT_PID) -> io:format("DISCONNECTED from MQTT!!!!!!\n"), mqtt_client:reconnect(whereis(mqtt_client)) end,
error_handler => fun(_MQTT_CLIENT_PID, Err) -> io:format("[~p:~p] ~p\n", [?MODULE, ?FUNCTION_NAME, Err]) end,
connected_handler => fun handle_connected/1
},
io:format("Starting 'mqtt_client'...~n"),
io:format("Starting 'mqtt_client'..."),
{ok, _MQTT_PID} = mqtt_client:start_link({local, mqtt_client}, MQTTConfig).
handle_call(start_client, _From, {_, _ReadyStatus}) ->
io:format("MQTT Controller received 'start_client' message from 'wifi' after obtaining IP address; starting 'mqtt_client'...~n"),
debugger:format("MQTT Controller received 'start_client' message from 'wifi' after obtaining IP address; starting 'mqtt_client'...\n"),
{ok, MQTT_PID} = start_mqtt_client(),
{reply, ok, {MQTT_PID, not_ready}};
handle_call({ready, MQTT_PID}, _From, {_, _ReadyStatus}) ->
@ -61,7 +61,7 @@ handle_call(get_pid, _From, State={MQTT_PID, _ReadyStatus}) ->
handle_call(get, _From, State={_MQTT_PID, _ReadyStatus}) ->
{reply, State, State};
handle_call(Msg, From, State) ->
io:format("MQTT Controller received unknown message ~p from ~p~n", [Msg, From]),
io:format("MQTT Controller received unknown message ~p from ~p\n", [Msg, From]),
{reply, ok, State}.
handle_cast({publish, Topic, Message}, State={_MQTT_PID, ReadyStatus}) -> %Fire-and-forget publish with no response
@ -78,24 +78,24 @@ terminate(_Reason, _State) ->
ac_on() ->
io:format("Turning on AC.~n", []),
io:format("Turning on AC.\n", []),
util:set_output(?FAN3, on),
util:set_output(?COMPRESSOR, on),
util:set_output(?STATUS_LED, on),
publish_message(?TOPIC_AC, <<"AC ON">>).
compressor_off() ->
io:format("Turning off compressor.~n", []),
io:format("Turning off compressor.\n", []),
util:set_output(?COMPRESSOR, off),
publish_message(?TOPIC_AC, <<"COMPRESSOR OFF">>).
compressor_on() ->
io:format("FORCE Turning ON compressor.~n", []),
io:format("FORCE Turning ON compressor.\n", []),
util:set_output(?COMPRESSOR, on),
publish_message(?TOPIC_AC, <<"COMPRESSOR OFF">>).
all_off() ->
io:format("Turning off compressor.~n", []),
io:format("Turning off compressor.\n", []),
util:set_output(?FAN3, off),
util:set_output(?FAN2, off),
util:set_output(?FAN1, off),
@ -115,14 +115,14 @@ publish_and_forget(Topic, Message) ->
handle_connected(MQTT) ->
Config = mqtt_client:get_config(MQTT),
debugger:format("[~p:~p] MQTT started and connected to ~p~n", [?MODULE, ?FUNCTION_NAME, maps:get(url, Config)]),
debugger:format("[~p:~p] MQTT started and connected to ~p", [?MODULE, ?FUNCTION_NAME, maps:get(url, Config)]),
gen_server:call(mqtt, {ready, MQTT}),
subscribe_to_topic_list(MQTT, get_topics()),
publish_message(?TOPIC_DEBUG, util:uptime()),
publish_message(?TOPIC_DEBUG, io_lib:format("[~p] '~p' running on [~p] started and connected!", [?MODULE, ?APPNAME, ?DEVICENAME])).
subscribe_to_topic(MQTT, Topic, SubHandleFunc, DataHandleFunc) ->
debugger:format("Subscribing to ~p...~n", [Topic]),
debugger:format("Subscribing to ~p...", [Topic]),
case mqtt_client:subscribe(MQTT, util:convert_to_binary(Topic), #{
%subscribed_handler => fun handle_subscribed/2,
%data_handler => fun handle_data/3
@ -130,7 +130,7 @@ subscribe_to_topic(MQTT, Topic, SubHandleFunc, DataHandleFunc) ->
data_handler => DataHandleFunc
}) of
ok -> ok;
_ -> io:format("MQTT Subscribe Failed! KILLING MQTT CLIENT ~p. My PID: ~p~n", [MQTT, self()]),
_ -> io:format("MQTT Subscribe Failed! KILLING MQTT CLIENT ~p. My PID: ~p", [MQTT, self()]),
exit(MQTT)
end.
@ -139,7 +139,7 @@ subscribe_to_topic_list(MQTT, Topics) ->
[{Topic, SubHandleFunc, DataHandleFunc}|Remaining] ->
subscribe_to_topic(MQTT, Topic, SubHandleFunc, DataHandleFunc),
subscribe_to_topic_list(MQTT, Remaining);
_ -> debugger:format("Done subscribing to MQTT topics.~n")
_ -> debugger:format("Done subscribing to MQTT topics.")
end.
get_topics() ->
@ -151,12 +151,12 @@ get_topics() ->
].
handle_subscribed(_MQTT, Topic) ->
debugger:format("Subscribed to topic: ~p.~n", [Topic]).
debugger:format("Subscribed to topic: ~p.", [Topic]).
unsubscribe(Topic) ->
{MQTT_PID, _ReadyStatus} = gen_server:call(?MODULE, get),
UnsubHandlerFunc = fun(_MQTT, UnsubTopic) -> debugger:format("Unsubscribed from topic feed: ~p ~n", [UnsubTopic]) end,
debugger:format("[mqtt:unsubscribe] Running mqtt:unsubscribe in mqtt.erl to mqtt_client ~p on topic: ~p~n",[MQTT_PID, Topic]),
UnsubHandlerFunc = fun(_MQTT, UnsubTopic) -> debugger:format("Unsubscribed from topic feed: ~p ", [UnsubTopic]) end,
debugger:format("[mqtt:unsubscribe] Running mqtt:unsubscribe in mqtt.erl to mqtt_client ~p on topic: ~p",[MQTT_PID, Topic]),
mqtt_client:unsubscribe(MQTT_PID, util:convert_to_binary(Topic), #{unsubscribed_handler => UnsubHandlerFunc}).
subscribe_remote_temp(Topic) ->
@ -167,16 +167,16 @@ subscribe_remote_temp(Topic) ->
end.
handle_data_remote_temp(_MQTT, Topic, Data) ->
debugger:format("[~p:~p/~p] remote temperature [~p] received from ~p~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Data, Topic]),
debugger:format("[~p:~p/~p] remote temperature [~p] received from ~p", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Data, Topic]),
temperature:set_remote_temperature(Data).
handle_subscribed_thermostat(_MQTT, Topic) ->
debugger:format("Subscribed to topic: ~p.~n", [Topic]), %,
debugger:format("Spawning thermostat setpoint publish loop on topic ~p~n", [?TOPIC_THERMOSTAT_SET]),
debugger:format("Subscribed to topic: ~p.", [Topic]), %,
debugger:format("Spawning thermostat setpoint publish loop on topic ~p", [?TOPIC_THERMOSTAT_SET]),
spawn(fun() -> publish_thermostat_loop(?THERMOSTAT_PUB_INTERVAL_SEC * 1000) end).
handle_data(_MQTT, Topic, Data) ->
debugger:format("[~p:~p/~p] received data on topic ~p: ~p ~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
debugger:format("[~p:~p/~p] received data on topic ~p: ~p", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
case Data of
<<"flash">> -> spawn(fun() -> led:flash(?STATUS_LED, 100, 20) end);
<<"flash2">> -> spawn(fun() -> led:flash(?STATUS_LED2, 300, 10) end);
@ -241,17 +241,17 @@ handle_data(_MQTT, Topic, Data) ->
end.
handle_data_thermostat(_MQTT, Topic, Data) ->
debugger:format("[~p:~p/~p] received data on topic ~p: ~p ~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
debugger:format("[~p:~p/~p] received data on topic ~p: ~p", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
case Data of
<<"+">> -> thermostat:up();
<<"up">> -> thermostat:up();
<<"-">> -> thermostat:down();
<<"down">> -> thermostat:down();
<<"span ", S/binary>> -> thermostat:set_span(S);
<<"show">> ->
Res = thermostat:get_thermostat(),
io:format("Thermostat: ~p~n", [Res]),
debugger:format("Thermostat: ~p", [Res]),
publish_message(?TOPIC_THERMOSTAT_SET, Res);
<<"span ", S/binary>> -> thermostat:set_span(S);
<<"save">> -> thermostat:save();
<<"load">> -> thermostat:load();
<<"default">> -> thermostat:default();
@ -263,7 +263,7 @@ handle_data_thermostat(_MQTT, Topic, Data) ->
end.
handle_data_fan(_MQTT, Topic, Data) ->
debugger:format("[~p:~p/~p] received data on topic ~p: ~p ~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
debugger:format("[~p:~p/~p] received data on topic ~p: ~p", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
case Data of
<<"cycle">> -> control:cycle_fan();
<<"1">> -> control:set_fan(1);
@ -273,7 +273,7 @@ handle_data_fan(_MQTT, Topic, Data) ->
end.
handle_data_output(_MQTT, Topic, Data) ->
debugger:format("~p/~p received data on topic ~p: ~p ~n", [?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
debugger:format("~p/~p received data on topic ~p: ~p", [?FUNCTION_NAME, ?FUNCTION_ARITY, Topic, Data]),
%binary:last gives the last byte of a binary as an integer (ASCII value in this case). Subtract 48 to get the output number. :)
Output = binary:last(Topic)-48,
%OutputBin = list_to_binary([Output+48]),
@ -302,7 +302,7 @@ publish_message(Topic, QoS, Data) ->
publish_message(Topic, QoS, Data, Timeout) ->
try
%io:format("Publishing data '~p' to topic ~p and mqtt_client pid ~p from my Pid ~p mqtt pid:~p ~n", [Data, Topic, whereis(mqtt_client), Self, whereis(mqtt)]),
%io:format("Publishing data '~p' to topic ~p and mqtt_client pid ~p from my Pid ~p mqtt pid:~p", [Data, Topic, whereis(mqtt_client), Self, whereis(mqtt)]),
io:format("MQTT Publishing '~p' to topic ~p~n", [Data, Topic]),
MQTT_CLIENT = whereis(mqtt_client),
Self = self(),


+ 1
- 1
src/network_sup.erl View File

@ -17,7 +17,7 @@ start_link() ->
supervisor:start_link({local, ?SERVER}, ?MODULE, []).
init([]) ->
io:format("Starting ~p supervisor with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting ~p supervisor with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
MaxRestarts = 3, % Kill everyone and die if more than MaxRestarts failures per MaxSecBetweenRestarts seconds
MaxSecBetweenRestarts = 60,
WiFi = worker(wifi, start_link, []),


+ 12
- 12
src/temperature.erl View File

@ -14,11 +14,11 @@
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
start_link() ->
debugger:format("Starting ~p with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting ~p with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
{ok, _Pid} = gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init(_) ->
debugger:format("[~p:~p/~p] Reading initial temperatures from thermistors on ~p and ~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, ?THERMISTOR1, ?THERMISTOR2]),
debugger:format("[~p:~p/~p] Reading initial temperatures from thermistors on ~p and ~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, ?THERMISTOR1, ?THERMISTOR2]),
{ok, ADC_T1_PID} = adc:start(?THERMISTOR1),
{ok, ADC_TCOIL_PID} = adc:start(?THERMISTOR2),
TempSource = format_source(esp:nvs_get_binary(?NVS_NAMESPACE, temp_source, <<"local">>)),
@ -32,16 +32,16 @@ init(_) ->
handle_info({subscribe_remote_temp, TempSource}, State) ->
case TempSource of
local -> ok; %do nothing for local
_ -> debugger:format("[~p:~p] subscribe_remote_temp attempting subscribe to remote source...~n", [?MODULE, ?FUNCTION_NAME]),
_ -> debugger:format("[~p:~p] subscribe_remote_temp attempting subscribe to remote source...", [?MODULE, ?FUNCTION_NAME]),
case whereis(mqtt) of
undefined ->
debugger:format("'mqtt' is not yet started, trying again later.~n"),
debugger:format("'mqtt' is not yet started, trying again later."),
erlang:send_after(10000, self(), {subscribe_remote_temp, TempSource});
_Pid -> case gen_server:call(mqtt, get) of
{_, ready} ->
mqtt:subscribe_remote_temp(TempSource);
_ ->
debugger:format("'mqtt' is running, but not ready, trying again later.~n"),
debugger:format("'mqtt' is running, but not ready, trying again later."),
erlang:send_after(10000, self(), {subscribe_remote_temp, TempSource})
end
end
@ -52,8 +52,8 @@ handle_info({tempread_loop, ADC_T1, ADC_TCOIL}, [_, {coiltemp, TCoil}, {temploca
T1 = read_temp(ADC_T1, thermistor1, TLocal),
Coil = read_temp(ADC_TCOIL, coil_thermistor, TCoil),
T = temp_select(T1, TRemote, TSrc),
%debugger:format("[~p:~p] tempread_loop [T=~.2f, TLocal=~.2f TCoil=~.2f, TRem=~p, TSrc=~p].~n", [?MODULE, ?FUNCTION_NAME, T, T1, Coil, TRemote, TSrc]),
debugger:format("[~p:~p] tempread_loop [T=~.2f, TLocal=~.2f TCoil=~.2f, TRem=~.2f, TSrc=~p].~n", [?MODULE, ?FUNCTION_NAME, T, T1, Coil, TRemote, TSrc]),
%debugger:format("[~p:~p] tempread_loop [T=~.2f, TLocal=~.2f TCoil=~.2f, TRem=~p, TSrc=~p].", [?MODULE, ?FUNCTION_NAME, T, T1, Coil, TRemote, TSrc]),
debugger:format("[~p:~p] tempread_loop [T=~.2f, TLocal=~.2f TCoil=~.2f, TRem=~.2f, TSrc=~p].", [?MODULE, ?FUNCTION_NAME, T, T1, Coil, TRemote, TSrc]),
erlang:send_after(15000, self(), {tempread_loop, ADC_T1, ADC_TCOIL}),
{noreply, [{temp, T}, {coiltemp, Coil}, {templocal, T1}, {tempremote, TRemote}, {tempsrc, TSrc}] }.
@ -82,11 +82,11 @@ terminate(_Reason, _State) ->
read_temp(ADC, Label, ErrDefaultVal) ->
case adc:read(ADC) of
{ok, {Raw, MilliVolts}} ->
debugger:format("[~p:~p] Read values from ADC ~p ~p: [Raw: ~p Voltage: ~pmV]~n", [?MODULE, ?FUNCTION_NAME, ADC, Label, Raw, MilliVolts]),
debugger:format("[~p:~p] Read values from ADC ~p ~p: [Raw: ~p Voltage: ~pmV]", [?MODULE, ?FUNCTION_NAME, ADC, Label, Raw, MilliVolts]),
%MilliVolts/1000;
convert_reading_to_F(MilliVolts);
Error ->
debugger:format("[~p:~p] Error taking reading from ADC ~p ~p: ~p~n", [?MODULE, ?FUNCTION_NAME, ADC, Label, Error]),
debugger:format("[~p:~p] Error taking reading from ADC ~p ~p: ~p", [?MODULE, ?FUNCTION_NAME, ADC, Label, Error]),
ErrDefaultVal
end.
@ -109,13 +109,13 @@ change_source(NewSrc, OldSrc) ->
BOldSrc = util:convert_to_binary(OldSrc),
if
BNewSrc == BOldSrc -> %Don't write to NVS or subscribe/unsubscribe if source is unchanged.
debugger:format("[~p:~p] Temp source is unchanged, keeping old.~n", [?MODULE, ?FUNCTION_NAME]),
debugger:format("[~p:~p] Temp source is unchanged, keeping old.", [?MODULE, ?FUNCTION_NAME]),
OldSrc;
true ->
Unsubscribed = case OldSrc of
local -> ok;
_ ->
debugger:format("[~p:~p] Unsubscribing from old source: ~p~n",[?MODULE, ?FUNCTION_NAME, OldSrc]),
debugger:format("[~p:~p] Unsubscribing from old source: ~p",[?MODULE, ?FUNCTION_NAME, OldSrc]),
mqtt:unsubscribe(OldSrc)
end,
case NewSrc of %new source is 'local' or a topic?
@ -123,7 +123,7 @@ change_source(NewSrc, OldSrc) ->
<<"local">> -> save_source(local);
_ -> case Unsubscribed of
ok ->
debugger:format("[~p:~p] We are unsubscribed from old source ~p. Subscribing to new: ~p~n",[?MODULE, ?FUNCTION_NAME, OldSrc, NewSrc]),
debugger:format("[~p:~p] We are unsubscribed from old source ~p. Subscribing to new: ~p",[?MODULE, ?FUNCTION_NAME, OldSrc, NewSrc]),
case mqtt:subscribe_remote_temp(NewSrc) of
ok -> save_source(NewSrc); %subscription was successful, so save only then
Error -> Error


+ 5
- 5
src/thermostat.erl View File

@ -14,14 +14,14 @@
-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
start_link() ->
debugger:format("Starting ~p with ~p/~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
debugger:format("Starting ~p with ~p/~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY]),
{ok, _Pid} = gen_server:start_link({local, ?MODULE}, ?MODULE, [?THERMOSTAT_DEFAULT, ?THERMOSTAT_SPAN_DEFAULT], []).
init(Args = [DefTempBinInt, DefSpanBinFloat]) ->
debugger:format("~p:~p/~p called with args: ~p...~n", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Args]),
debugger:format("~p:~p/~p called with args: ~p...", [?MODULE, ?FUNCTION_NAME, ?FUNCTION_ARITY, Args]),
StartTemp = esp:nvs_get_binary(?NVS_NAMESPACE, thermostat, DefTempBinInt),
SpanDegrees = esp:nvs_get_binary(?NVS_NAMESPACE, span, DefSpanBinFloat),
debugger:format("[~p:~p] Setting initial values. Temp: ~p Span: ~p~n", [?MODULE, ?FUNCTION_NAME, StartTemp, SpanDegrees]),
debugger:format("[~p:~p] Setting initial values. Temp: ~p Span: ~p", [?MODULE, ?FUNCTION_NAME, StartTemp, SpanDegrees]),
{ok, [{temp, binary_to_integer(StartTemp)}, {span, binary_to_float(SpanDegrees)}]}.
handle_info({set_temp, Temp}, State=[_T, Span]) ->
@ -47,12 +47,12 @@ handle_call({load}, _From, _State=[_T, Span]) ->
StoredTemp = esp:nvs_get_binary(?NVS_NAMESPACE, thermostat, ?THERMOSTAT_DEFAULT),
{reply, ok, [{temp, binary_to_integer(StoredTemp)}, Span]};
handle_call({save}, _From, State=[{temp, Temp}, {span, Span}]) ->
debugger:format("[~p:~p] Saving current thermostat value: ~p~n", [?MODULE, ?FUNCTION_NAME, Temp]),
debugger:format("[~p:~p] Saving current thermostat value: ~p", [?MODULE, ?FUNCTION_NAME, Temp]),
esp:nvs_set_binary(?NVS_NAMESPACE, thermostat, integer_to_binary(Temp)),
esp:nvs_set_binary(?NVS_NAMESPACE, span, float_to_binary(Span, [{decimals, 1}])),
{reply, ok, State};
handle_call({set_span, Span}, _From, [{temp, Temp}|_]) ->
debugger:format("[~p:~p] Setting new span value: ~p~n", [?MODULE, ?FUNCTION_NAME, Span]),
debugger:format("[~p:~p] Setting new span value: ~p", [?MODULE, ?FUNCTION_NAME, Span]),
{reply, ok, [{temp, Temp}, {span, Span/1}]}; %divide by one forces float
handle_call(get, _From, State) ->
{reply, State, State};


+ 7
- 9
src/util.erl View File

@ -38,9 +38,9 @@ set_output_activelow(Pin, State) ->
end.
print_time() ->
%debugger:format("Printing Time with ~p...~n", [?FUNCTION_NAME]),
%debugger:format("Printing Time with ~p...", [?FUNCTION_NAME]),
{{Year, Month, Day}, {Hour, Minute, Second}} = erlang:universaltime(),
debugger:format("Date: ~p/~2..0p/~2..0p ~2..0p:~2..0p:~2..0p (~pms)~n", [
debugger:format("Date: ~p/~2..0p/~2..0p ~2..0p:~2..0p:~2..0p (~pms)", [
Year, Month, Day, Hour, Minute, Second, erlang:system_time(millisecond)
]),
{{Year, Month, Day}, {Hour, Minute, Second}}.
@ -69,13 +69,11 @@ uptime() ->
%%% FUNCTION TIMER
timer(Param, Val, Time) when is_binary(Time) ->
{T, M} = parse_timer_time(Time),
io:format("PARSED TIME: ~p, ~p ", [T, M]),
timer(Param, Val, T, M);
timer(Param, Val, Time) ->
timer(Param, Val, Time, s),
io:format("PARSED TIME 22222 where time is not binary: ~p, ~p ", [x, x]).
timer(Param, Val, Time, Multiplier) ->
io:format("[~p:~p] processing timer...~n", [?MODULE, ?FUNCTION_NAME]),
io:format("[~p:~p] processing timer...", [?MODULE, ?FUNCTION_NAME]),
T = make_int(Time),
M = multiplier_from_specifier(Multiplier),
MultP = parse_multiplier(Multiplier),
@ -116,7 +114,7 @@ timer(Param, Val, Time, Multiplier) ->
parse_timer_time(T) when is_integer(T) -> {T, s};
parse_timer_time(T) when is_binary(T) ->
%io:format("[~p:~p] parsing timer time from binary...~n", [?MODULE, ?FUNCTION_NAME]),
%debugger:format("[~p:~p] parsing timer time from binary...", [?MODULE, ?FUNCTION_NAME]),
S = byte_size(T),
{Time, MultiplierSuffix} = case binary:last(T) of
100 -> binary_split(T, S-1); %d = days
@ -182,14 +180,14 @@ beep(Freq, DurationMs) ->
beep(Freq, DurationMs - CyclePeriod). %not accurate length, but good enough
%beep_pwm(Freq, Duration) ->
% io:format("beeping at freq ~p for duration ~p ms.~n", [Freq, Duration]),
% io:format("beeping at freq ~p for duration ~p ms.", [Freq, Duration]),
% Freq = Freq,
% {ok, Timer} = ledc_pwm:create_timer(Freq),
% io:format("Timer: ~p~n", [Timer]),
% io:format("Timer: ~p", [Timer]),
%
% {ok, Beeper} = ledc_pwm:create_channel(Timer, ?BEEPER),
% %{ok, Beeper} = ledc_pwm:create_channel(Timer, 25),
% io:format("Channel1: ~p~n", [Beeper]),
% io:format("Channel1: ~p", [Beeper]),
%
% %FadeupMs = make_int(Duration),
% FadeupMs = make_int(Duration/0.9),


+ 12
- 12
src/wifi.erl View File

@ -33,7 +33,7 @@ start_link() ->
],
case network:start_link(Config) of
{ok, _Pid} ->
debugger:format("Network started.~n"),
debugger:format("Network started."),
{ok, _Pid};
%timer:sleep(infinity);
Error ->
@ -41,41 +41,41 @@ start_link() ->
end.
ap_started() ->
debugger:format("AP started.~n").
debugger:format("AP started.").
sta_connected(Mac) ->
debugger:format("WiFi AP: Station connected with mac ~p~n", [Mac]).
debugger:format("WiFi AP: Station connected with mac ~p", [Mac]).
sta_disconnected(Mac) ->
debugger:format("WiFi AP: Station ~p disconnected~n", [Mac]).
debugger:format("WiFi AP: Station ~p disconnected.", [Mac]).
sta_ip_assigned(Address) ->
debugger:format("WiFi AP: Station assigned address ~p~n", [Address]).
debugger:format("WiFi AP: Station assigned address ~p", [Address]).
connected() ->
debugger:format("WiFi Client: connected.~n").
debugger:format("WiFi Client: connected.").
got_ip(IpInfo) ->
debugger:format("WiFi Client: Using IP address: ~p.~n", [IpInfo]),
debugger:format("WiFi Client: Using IP address: ~p.", [IpInfo]),
% network_services_sup:start_link(). %We have an IP address, so start our network dependant services supervisor
case whereis(mqtt) of
undefined ->
debugger:format("MQTT CONTROLLER NOT RUNNING??~n");
debugger:format("MQTT CONTROLLER NOT RUNNING??");
_Pid -> gen_server:call(mqtt, start_client)
end,
ok.
disconnected() ->
debugger:format("WiFi Client: disconnected.~n"),
debugger:format("WiFi Client: disconnected."),
timer:sleep(10000),
debugger:format("WiFi [not] killing myself because of disconnection...~n"),
debugger:format("WiFi [not] killing myself because of disconnection..."),
timer:sleep(1).
%exit(kill). %kill myself (supervisor will restart) FIXME: is this best way to handle this??
sntp_synchronized({TVSec, TVUsec}) ->
debugger:format("Synchronized time with SNTP server. TVSec=~p TVUsec=~p~n", [TVSec, TVUsec]),
debugger:format("Synchronized time with SNTP server. TVSec=~p TVUsec=~p", [TVSec, TVUsec]),
util:print_time(),
debugger:format("Updating system boot time...~n"),
debugger:format("Updating system boot time..."),
debugger:set_boot_time(),
mqtt:publish_and_forget(?TOPIC_DEBUG, util:uptime()).

Loading…
Cancel
Save