%%%------------------------------------------------------------------- %%% @author licheng5 %%% @copyright (C) 2020, %%% @doc %%% %%% @end %%% Created : 11. 12月 2020 上午10:57 %%%------------------------------------------------------------------- -module(iot_util). -author("licheng5"). %% API -export([timestamp/0, number_format/2, current_time/0, timestamp_of_seconds/0, float_to_binary/2, int_format/2]). -export([step/3, rand_bytes/1, uuid/0, md5/1, parse_mapper/1]). -export([json_data/1, json_error/2, is_json/1]). -export([queue_limited_in/3, assert_call/2, assert/2]). -export([sha256/1]). -spec is_json(Json :: term()) -> boolean(). is_json(Json) when is_binary(Json) -> case catch json:decode(Json) of Result when is_list(Result) orelse is_map(Result) -> true; _ -> false end; is_json(_Json) -> false. %% 时间,精确到毫秒 timestamp() -> {Mega, Seconds, Micro} = os:timestamp(), (Mega * 1000000 + Seconds) * 1000 + Micro div 1000. current_time() -> {Mega, Seconds, _Micro} = os:timestamp(), Mega * 1000000 + Seconds. timestamp_of_seconds() -> {Mega, Seconds, _Micro} = os:timestamp(), Mega * 1000000 + Seconds. number_format(Num, _Decimals) when is_integer(Num) -> Num; number_format(Float, Decimals) when is_float(Float) -> list_to_float(float_to_list(Float, [{decimals, Decimals}, compact])). int_format(Num, Len) when is_integer(Num), Len > 0 -> S = integer_to_list(Num), case length(S) > Len of true -> list_to_integer(lists:sublist(S, 1, Len)); false -> Num end. step(Start, End, Step) when is_integer(Start), is_integer(End), is_integer(Step), Start < End, Step > 0 -> step(Start, End, Step, []). step(Start, End, Step, Acc) when Start < End -> step(Start + Step, End, Step, [{Start, min(Start + Step, End)} | Acc]); step(_, _, _, Acc) -> lists:reverse(Acc). json_data(Data) -> iolist_to_binary(json:encode(#{ <<"result">> => Data })). json_error(ErrCode, ErrMessage) when is_integer(ErrCode) -> iolist_to_binary(json:encode(#{ <<"error">> => #{ <<"code">> => ErrCode, <<"message">> => ErrMessage } })). uuid() -> rand_bytes(16). -spec rand_bytes(Size :: integer()) -> string(). rand_bytes(Size) when is_integer(Size), Size > 0 -> Size1 = erlang:ceil(Size / 2), Bytes = crypto:strong_rand_bytes(Size1), S = lists:flatten([integer_to_list(E, 16) || <> <= Bytes]), lists:sublist(string:to_lower(S), 1, Size). queue_limited_in(Item, Q, Num) when is_integer(Num) -> case queue:len(Q) >= Num of true -> Q1 = queue:drop(Q), queue:in(Item, Q1); false -> queue:in(Item, Q) end. assert_call(true, Fun) -> Fun(); assert_call(false, _) -> ok. -spec sha256(Str :: string() | binary()) -> binary(). sha256(Str) when is_list(Str) -> sha256(unicode:characters_to_binary(Str)); sha256(Bin) when is_binary(Bin) -> HashBin = crypto:hash(sha256, Bin), HexStr = lists:flatten([io_lib:format("~2.16.0B", [B]) || B <- binary:bin_to_list(HashBin)]), list_to_binary(string:lowercase(HexStr)). -spec md5(Str :: binary()) -> binary(). md5(Str) when is_binary(Str) -> list_to_binary(lists:flatten([hex(X) || <> <= erlang:md5(Str)])). hex(N) when N < 10 -> $0 + N; hex(N) -> $a + (N - 10). %% 转换映射器 -spec parse_mapper(Mapper :: binary() | string()) -> error | {ok, F :: fun((binary(), any()) -> any())}. parse_mapper(_Mapper) -> %% Dynamic Erlang eval is intentionally disabled in runtime code. error. -spec float_to_binary(Num :: number(), integer()) -> binary(). float_to_binary(V, _) when is_integer(V) -> integer_to_binary(V); float_to_binary(V, Decimals) when is_float(V), is_integer(Decimals) -> S = float_to_list(V, [{decimals, Decimals}, compact]), list_to_binary(S). assert(true, _) -> ok; assert(false, F) when is_function(F) -> F(); assert(false, Msg) -> throw(Msg).