aircon/apps/aircon/src/aircon_args.erl
2026-01-08 15:17:17 +08:00

159 lines
5.8 KiB
Erlang
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%%%-------------------------------------------------------------------
%%% @author aresei
%%% @copyright (C) 2023, <COMPANY>
%%% @doc
%%%
%%% @end
%%% Created : 06. 9月 2023 16:37
%%%-------------------------------------------------------------------
-module(aircon_args).
-author("aresei").
-behaviour(gen_server).
%% API
-export([start_link/0]).
-export([get_metric/0, get_param/0, push_metric/1, push_param/1, get_device_uuid/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-define(SERVER, ?MODULE).
-record(state, {
%% #{device_id => device_uuid}, 下发的时候是serial
metrics = #{},
param = #{}
}).
%%%===================================================================
%%% API
%%%===================================================================
-spec get_param() -> {ok, Param :: #{}}.
get_param() ->
gen_server:call(?MODULE, get_param).
-spec get_metric() -> {ok, Metric :: map()}.
get_metric() ->
gen_server:call(?MODULE, get_metric).
-spec get_device_uuid(DeviceId :: binary()) -> error | {ok, DeviceUUID :: binary()}.
get_device_uuid(DeviceId) when is_binary(DeviceId) ->
gen_server:call(?MODULE, {get_device_uuid, DeviceId}).
-spec push_param(Param :: map()) -> no_return().
push_param(Param) when is_map(Param) ->
gen_server:cast(?MODULE, {push_param, Param}).
-spec push_metric(Metrics :: list()) -> no_return().
push_metric(Metrics) when is_list(Metrics) ->
gen_server:cast(?MODULE, {push_metric, Metrics}).
%% @doc Spawns the server and registers the local name (unique)
-spec(start_link() ->
{ok, Pid :: pid()} | ignore | {error, Reason :: term()}).
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
%% @private
%% @doc Initializes the server
-spec(init(Args :: term()) ->
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
{stop, Reason :: term()} | ignore).
init([]) ->
{ok, Metrics} = efka_client:request_metric(),
try convert_metric(Metrics) of
{ok, MetricMap} ->
logger:debug("[aircon_args] init load metric_map: ~p", [MetricMap]),
{ok, Param} = efka_client:request_param(),
{ok, #state{metrics = MetricMap, param = Param}}
catch
_:Error:Stack->
logger:warning("[aircon_args] request_metric get error: ~p, stack: ~p", [Error, Stack]),
{ok, #state{metrics = #{}, param = #{}}}
end.
%% @private
%% @doc Handling call messages
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
State :: #state{}) ->
{reply, Reply :: term(), NewState :: #state{}} |
{reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
{noreply, NewState :: #state{}} |
{noreply, NewState :: #state{}, timeout() | hibernate} |
{stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
{stop, Reason :: term(), NewState :: #state{}}).
handle_call(get_param, _From, State = #state{param = Param}) ->
{reply, {ok, Param}, State};
handle_call({get_device_uuid, DeviceId}, _From, State = #state{metrics = Metrics}) when is_map(Metrics) ->
Result = maps:find(DeviceId, Metrics),
{reply, Result, State};
handle_call({get_device_uuid, _DeviceId}, _From, State) ->
{reply, error, State};
handle_call(get_metric, _From, State = #state{metrics = Metrics}) ->
{reply, {ok, Metrics}, State}.
%% @private
%% @doc Handling cast messages
-spec(handle_cast(Request :: term(), State :: #state{}) ->
{noreply, NewState :: #state{}} |
{noreply, NewState :: #state{}, timeout() | hibernate} |
{stop, Reason :: term(), NewState :: #state{}}).
handle_cast({push_param, Param}, State = #state{}) ->
{noreply, State#state{param = Param}};
handle_cast({push_metric, Metrics}, State = #state{}) ->
try convert_metric(Metrics) of
{ok, MetricMap} ->
logger:debug("[aircon_args] push metric_map: ~p", [MetricMap]),
{noreply, State#state{metrics = MetricMap}}
catch _:_ ->
{noreply, State}
end.
%% @private
%% @doc Handling all non call/cast messages
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
{noreply, NewState :: #state{}} |
{noreply, NewState :: #state{}, timeout() | hibernate} |
{stop, Reason :: term(), NewState :: #state{}}).
handle_info(_Info, State = #state{}) ->
{noreply, State}.
%% @private
%% @doc This function is called by a gen_server when it is about to
%% terminate. It should be the opposite of Module:init/1 and do any
%% necessary cleaning up. When it returns, the gen_server terminates
%% with Reason. The return value is ignored.
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
State :: #state{}) -> term()).
terminate(_Reason, _State = #state{}) ->
ok.
%% @private
%% @doc Convert process state when code is changed
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
Extra :: term()) ->
{ok, NewState :: #state{}} | {error, Reason :: term()}).
code_change(_OldVsn, State = #state{}, _Extra) ->
{ok, State}.
%%%===================================================================
%%% Internal functions
%%%===================================================================
-spec convert_metric(Metrics :: list()) -> {ok, map()}.
convert_metric(Metrics) when is_list(Metrics) ->
MetricTuples = lists:flatmap(fun
(#{<<"serial">> := DeviceId, <<"device_uuid">> := DeviceUUID}) ->
[{DeviceId, DeviceUUID}];
(_) ->
[]
end, Metrics),
{ok, maps:from_list(MetricTuples)}.