diff --git a/.gitignore b/.gitignore index f1c4554..acfddff 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ _build *.iml rebar3.crashdump *~ +config/sys.config diff --git a/apps/njau_bot/src/http_handler/api_handler.erl b/apps/njau_bot/src/http_handler/api_handler.erl index 50bcd44..2f8a653 100644 --- a/apps/njau_bot/src/http_handler/api_handler.erl +++ b/apps/njau_bot/src/http_handler/api_handler.erl @@ -25,49 +25,78 @@ init(Req0, Opts) -> }, Resp, Req1), {ok, Req2, Opts}. - %% 场地信息 handle_request("POST", "/api/device_info/storeInfo", ReqBody) when is_binary(ReqBody) -> #{<<"storeInfos">> := StoreInfos} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get storeInfo: ~p", [StoreInfos]), - - njau_bot_logger:write(ReqBody), + lists:foreach(fun(Info) -> + Msg = jiffy:encode(Info, [force_utf8]), + case catch njau_bot_database:insert_store_info(Info) of + {ok, _} -> + njau_bot_logger:write([<<"storeInfo: OK">>, Msg]); + {error, Error} -> + njau_bot_logger:write([<<"storeInfo: ERROR">>, Msg, format_error(Error)]) + end + end, StoreInfos), {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; %% 设备信息 handle_request("POST", "/api/device_info/equip", ReqBody) -> #{<<"equips">> := Equips} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get equips: ~p", [Equips]), - - njau_bot_logger:write(ReqBody), + lists:foreach(fun(Fields) -> + Msg = jiffy:encode(Fields, [force_utf8]), + case catch njau_bot_database:insert_equip(Fields) of + {ok, _} -> + njau_bot_logger:write([<<"equip: OK">>, Msg]); + {error, Error} -> + njau_bot_logger:write([<<"equip: ERROR">>, Msg, format_error(Error)]) + end + end, Equips), {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; %% 设备离线,在线状态 handle_request("POST", "/api/device_info/online", ReqBody) -> - #{<<"equipStatus">> := Equips} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get online: ~p", [Equips]), - - njau_bot_logger:write(ReqBody), + #{<<"equipStatus">> := EquipStatus} = jiffy:decode(ReqBody, [return_maps]), + lists:foreach(fun(Fields) -> + Msg = jiffy:encode(Fields, [force_utf8]), + case catch njau_bot_database:insert_equip_status(Fields) of + {ok, _} -> + njau_bot_logger:write([<<"equipStatus: OK">>, Msg]); + {error, Error} -> + njau_bot_logger:write([<<"equipStatus: ERROR">>, Msg, format_error(Error)]) + end + end, EquipStatus), {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; %% 设备运行状态 handle_request("POST", "/api/device_info/runStatus", ReqBody) -> #{<<"equipRunStatus">> := EquipRunStatus} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get equipRunStatus: ~p", [EquipRunStatus]), - - njau_bot_logger:write(ReqBody), + lists:foreach(fun(Fields) -> + Msg = jiffy:encode(Fields, [force_utf8]), + case catch njau_bot_database:insert_run_status(Fields) of + {ok, _} -> + njau_bot_logger:write([<<"equipRunStatus: OK">>, Msg]); + {error, Error} -> + njau_bot_logger:write([<<"equipRunStatus: ERROR">>, Msg, format_error(Error)]) + end + end, EquipRunStatus), {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; %% 订单信息推送 handle_request("POST", "/api/device_info/order", ReqBody) -> - %#{<<"equipRunStatus">> := EquipRunStatus} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get order: ~p", [ReqBody]), - - njau_bot_logger:write(ReqBody), + #{<<"orderInfos">> := OrderInfos} = jiffy:decode(ReqBody, [return_maps]), + lists:foreach(fun(Order) -> + Msg = jiffy:encode(Order, [force_utf8]), + case catch njau_bot_database:insert_order(Order) of + {ok, _} -> + njau_bot_logger:write([<<"order: OK">>, Msg]); + {error, Error} -> + njau_bot_logger:write([<<"order: ERROR">>, Msg, format_error(Error)]) + end + end, OrderInfos), {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; @@ -104,4 +133,11 @@ json_reply(Result, Message) when is_boolean(Result), is_binary(Message) -> <<"result">> => Result, <<"message">> => Message }, [force_utf8]), - iolist_to_binary(Json). \ No newline at end of file + iolist_to_binary(Json). + +format_error({_, Message}) when is_binary(Message) -> + Message; +format_error(Message) when is_binary(Message) -> + Message; +format_error(Err) -> + iolist_to_binary(io_lib:format("~p", [Err])). \ No newline at end of file diff --git a/apps/njau_bot/src/http_handler/api_handler1.erl b/apps/njau_bot/src/http_handler/api_handler1.erl deleted file mode 100644 index 2e88a96..0000000 --- a/apps/njau_bot/src/http_handler/api_handler1.erl +++ /dev/null @@ -1,118 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author licheng5 -%%% @copyright (C) 2020, -%%% @doc -%%% -%%% @end -%%% Created : 26. 4月 2020 3:36 下午 -%%%------------------------------------------------------------------- --module(api_handler1). --author("licheng5"). - -%% API --export([init/2]). - -init(Req0, Opts) -> - Method = binary_to_list(cowboy_req:method(Req0)), - Path = binary_to_list(cowboy_req:path(Req0)), - - {ok, ReqBody, Req1} = parse_body(Req0), - Sign = cowboy_req:header(<<"sign">>, Req1, <<>>), - BodySign = njau_bot_signer:sign(ReqBody), - case BodySign =:= string:lowercase(Sign) of - true -> - {ok, StatusCode, Resp} = handle_request(Method, Path, ReqBody), - lager:debug("[http_protocol] request path: ~p, post_params: ~p, response: ~ts", - [Path, ReqBody, Resp]), - Req2 = cowboy_req:reply(StatusCode, #{ - <<"Content-Type">> => <<"application/json">> - }, Resp, Req1), - {ok, Req2, Opts}; - false -> - lager:debug("[api_handler] invalid sign: ~p, body sign: ~p, request body: ``~ts``", [Sign, BodySign, ReqBody]), - Req2 = cowboy_req:reply(500, #{ - <<"Content-Type">> => <<"text/html;charset=utf-8">> - }, <<"Internal Server Error">>, Req1), - {ok, Req2, Opts} - end. - -%% 场地信息 -handle_request("POST", "/api/device_info/storeInfo", ReqBody) when is_binary(ReqBody) -> - #{<<"storeInfos">> := StoreInfos} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get storeInfo: ~p", [StoreInfos]), - - njau_bot_logger:write(ReqBody), - - {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; - -%% 设备信息 -handle_request("POST", "/api/device_info/equip", ReqBody) -> - #{<<"equips">> := Equips} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get equips: ~p", [Equips]), - - njau_bot_logger:write(ReqBody), - - {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; - -%% 设备离线,在线状态 -handle_request("POST", "/api/device_info/online", ReqBody) -> - #{<<"equipStatus">> := Equips} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get online: ~p", [Equips]), - - njau_bot_logger:write(ReqBody), - - {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; - -%% 设备运行状态 -handle_request("POST", "/api/device_info/runStatus", ReqBody) -> - #{<<"equipRunStatus">> := EquipRunStatus} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get equipRunStatus: ~p", [EquipRunStatus]), - - njau_bot_logger:write(ReqBody), - - {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; - -%% 订单信息推送 -handle_request("POST", "/api/device_info/order", ReqBody) -> - %#{<<"equipRunStatus">> := EquipRunStatus} = jiffy:decode(ReqBody, [return_maps]), - lager:debug("[api_handler] get order: ~p", [ReqBody]), - - njau_bot_logger:write(ReqBody), - - {ok, 200, json_reply(true, <<"接收成功"/utf8>>)}; - -handle_request(_, Path, _) -> - Path1 = list_to_binary(Path), - {ok, 200, json_reply(false, <<"url: ", Path1/binary, " not found">>)}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% helper methods -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -parse_body(Req0) -> - ContentType = cowboy_req:header(<<"content-type">>, Req0), - case ContentType of - <<"application/json", _/binary>> -> - {ok, Body, Req1} = read_body(Req0), - {ok, Body, Req1}; - _ -> - {ok, #{}, Req0} - end. - -%% 读取请求体 -read_body(Req) -> - read_body(Req, <<>>). -read_body(Req, AccData) -> - case cowboy_req:read_body(Req) of - {ok, Data, Req1} -> - {ok, <>, Req1}; - {more, Data, Req1} -> - read_body(Req1, <>) - end. - -json_reply(Result, Message) when is_boolean(Result), is_binary(Message) -> - Json = jiffy:encode(#{ - <<"result">> => Result, - <<"message">> => Message - }, [force_utf8]), - iolist_to_binary(Json). \ No newline at end of file diff --git a/apps/njau_bot/src/msyql_driver/mysql_pool.erl b/apps/njau_bot/src/msyql_driver/mysql_pool.erl new file mode 100644 index 0000000..deab3c8 --- /dev/null +++ b/apps/njau_bot/src/msyql_driver/mysql_pool.erl @@ -0,0 +1,50 @@ +%%%------------------------------------------------------------------- +%%% @author aresei +%%% @copyright (C) 2018, +%%% @doc +%%% +%%% @end +%%% Created : 29. 九月 2018 17:01 +%%%------------------------------------------------------------------- +-module(mysql_pool). +-author("aresei"). + +%% API +-export([get_row/1, get_row/2, get_all/1, get_all/2]). +-export([update/3, update_by/1, update_by/2, insert/3]). + +-define(POOL, mysql_bot). + +%% 从数据库中查找一行记录 +-spec get_row(Sql::binary()) -> {ok, Record::map()} | undefined. +get_row(Sql) when is_binary(Sql) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:get_row(ConnPid, Sql) end). + +-spec get_row(Sql::binary(), Params::list()) -> {ok, Record::map()} | undefined. +get_row(Sql, Params) when is_binary(Sql), is_list(Params) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:get_row(ConnPid, Sql, Params) end). + +-spec get_all(Sql::binary()) -> {ok, Rows::list()} | {error, Reason :: any()}. +get_all(Sql) when is_binary(Sql) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:get_all(ConnPid, Sql) end). + +-spec get_all(Sql::binary(), Params::list()) -> {ok, Rows::list()} | {error, Reason::any()}. +get_all(Sql, Params) when is_binary(Sql), is_list(Params) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:get_all(ConnPid, Sql, Params) end). + +-spec insert(Table :: binary(), Fields :: map() | list(), boolean()) -> + ok | {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert(Table, Fields, FetchInsertId) when is_binary(Table), is_list(Fields); is_map(Fields), is_boolean(FetchInsertId) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:insert(ConnPid, Table, Fields, FetchInsertId) end). + +-spec update_by(UpdateSql :: binary()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. +update_by(UpdateSql) when is_binary(UpdateSql) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:update_by(ConnPid, UpdateSql) end). + +-spec update_by(UpdateSql :: binary(), Params :: list()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. +update_by(UpdateSql, Params) when is_binary(UpdateSql) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:update_by(ConnPid, UpdateSql, Params) end). + +-spec update(Table :: binary(), Fields :: map(), WhereFields :: map()) -> {ok, AffectedRows::integer()} | {error, Reason::any()}. +update(Table, Fields, WhereFields) when is_binary(Table), is_map(Fields), is_map(WhereFields) -> + poolboy:transaction(?POOL, fun(ConnPid) -> mysql_provider:update(ConnPid, Table, Fields, WhereFields) end). \ No newline at end of file diff --git a/apps/njau_bot/src/msyql_driver/mysql_provider.erl b/apps/njau_bot/src/msyql_driver/mysql_provider.erl new file mode 100644 index 0000000..7415f9d --- /dev/null +++ b/apps/njau_bot/src/msyql_driver/mysql_provider.erl @@ -0,0 +1,144 @@ +%%%------------------------------------------------------------------- +%%% @author aresei +%%% @copyright (C) 2018, +%%% @doc +%%% +%%% @end +%%% Created : 29. 九月 2018 17:01 +%%%------------------------------------------------------------------- +-module(mysql_provider). +-author("aresei"). + +%% API +-export([get_row/2, get_row/3, get_all/2, get_all/3]). +-export([update/4, update_by/2, update_by/3, insert/4]). + +%% 从数据库中查找一行记录 +-spec get_row(ConnPid :: pid(), Sql::binary()) -> {ok, Record::map()} | undefined. +get_row(ConnPid, Sql) when is_pid(ConnPid), is_binary(Sql) -> + lager:debug("[mysql_client] get_row sql is: ~p", [Sql]), + case mysql:query(ConnPid, Sql) of + {ok, Names, [Row | _]} -> + {ok, maps:from_list(lists:zip(Names, Row))}; + {ok, _, []} -> + undefined; + Error -> + lager:warning("[mysql_client] get error: ~p", [Error]), + undefined + end. + +-spec get_row(ConnPid :: pid(), Sql::binary(), Params::list()) -> {ok, Record::map()} | undefined. +get_row(ConnPid, Sql, Params) when is_pid(ConnPid), is_binary(Sql), is_list(Params) -> + lager:debug("[mysql_client] get_row sql is: ~p, params: ~p", [Sql, Params]), + case mysql:query(ConnPid, Sql, Params) of + {ok, Names, [Row | _]} -> + {ok, maps:from_list(lists:zip(Names, Row))}; + {ok, _, []} -> + undefined; + Error -> + lager:warning("[mysql_client] get error: ~p", [Error]), + undefined + end. + +-spec get_all(ConnPid :: pid(), Sql::binary()) -> {ok, Rows::list()} | {error, Reason :: any()}. +get_all(ConnPid, Sql) when is_pid(ConnPid), is_binary(Sql) -> + lager:debug("[mysql_client] get_all sql is: ~p", [Sql]), + case mysql:query(ConnPid, Sql) of + {ok, Names, Rows} -> + {ok, lists:map(fun(Row) -> maps:from_list(lists:zip(Names, Row)) end, Rows)}; + {error, Reason} -> + lager:warning("[mysql_client] get error: ~p", [Reason]), + {error, Reason} + end. + +-spec get_all(ConnPid :: pid(), Sql::binary(), Params::list()) -> {ok, Rows::list()} | {error, Reason::any()}. +get_all(ConnPid, Sql, Params) when is_pid(ConnPid), is_binary(Sql), is_list(Params) -> + lager:debug("[mysql_client] get_all sql is: ~p, params: ~p", [Sql, Params]), + case mysql:query(ConnPid, Sql, Params) of + {ok, Names, Rows} -> + {ok, lists:map(fun(Row) -> maps:from_list(lists:zip(Names, Row)) end, Rows)}; + {error, Reason} -> + lager:warning("[mysql_client] get error: ~p", [Reason]), + {error, Reason} + end. + +-spec insert(ConnPid :: pid(), Table :: binary(), Fields :: map() | list(), boolean()) -> + ok | {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert(ConnPid, Table, Fields, FetchInsertId) when is_pid(ConnPid), is_binary(Table), is_map(Fields), is_boolean(FetchInsertId) -> + insert(ConnPid, Table, maps:to_list(Fields), FetchInsertId); +insert(ConnPid, Table, Fields, FetchInsertId) when is_pid(ConnPid), is_binary(Table), is_list(Fields), is_boolean(FetchInsertId) -> + {Keys, Values} = kvs(Fields), + + FieldSql = iolist_to_binary(lists:join(<<", ">>, Keys)), + Placeholders = lists:duplicate(length(Keys), <<"?">>), + ValuesPlaceholder = iolist_to_binary(lists:join(<<", ">>, Placeholders)), + + Sql = <<"INSERT INTO ", Table/binary, "(", FieldSql/binary, ") VALUES(", ValuesPlaceholder/binary, ")">>, + lager:debug("[mysql_client] insert sql is: ~p, params: ~p", [Sql, Values]), + case mysql:query(ConnPid, Sql, Values) of + ok -> + case FetchInsertId of + true -> + InsertId = mysql:insert_id(ConnPid), + {ok, InsertId}; + false -> + ok + end; + Error -> + Error + end. + +-spec update_by(ConnPid :: pid(), UpdateSql :: binary()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. +update_by(ConnPid, UpdateSql) when is_pid(ConnPid), is_binary(UpdateSql) -> + lager:debug("[mysql_client] updateBySql sql: ~p", [UpdateSql]), + case mysql:query(ConnPid, UpdateSql) of + ok -> + AffectedRows = mysql:affected_rows(ConnPid), + {ok, AffectedRows}; + Error -> + Error + end. + +-spec update_by(ConnPid :: pid(), UpdateSql :: binary(), Params :: list()) -> {ok, AffectedRows :: integer()} | {error, Reason :: any()}. +update_by(ConnPid, UpdateSql, Params) when is_pid(ConnPid), is_binary(UpdateSql) -> + lager:debug("[mysql_client] updateBySql sql: ~p, params: ~p", [UpdateSql, Params]), + case mysql:query(ConnPid, UpdateSql, Params) of + ok -> + AffectedRows = mysql:affected_rows(ConnPid), + {ok, AffectedRows}; + Error -> + Error + end. + +-spec update(ConnPid :: pid(), Sql :: binary(), Fields :: map(), WhereFields :: map()) -> + {ok, AffectedRows::integer()} | {error, Reason::any()}. +update(ConnPid, Table, Fields, WhereFields) when is_pid(ConnPid), is_binary(Table), is_map(Fields), is_map(WhereFields) -> + %% 拼接set + {SetKeys, SetVals} = kvs(Fields), + SetKeys1 = lists:map(fun(K) when is_binary(K) -> <<"`", K/binary, "` = ?">> end, SetKeys), + SetSql = iolist_to_binary(lists:join(<<", ">>, SetKeys1)), + + %% 拼接where + {WhereKeys, WhereVals} = kvs(WhereFields), + WhereKeys1 = lists:map(fun(K) when is_binary(K) -> <<"`", K/binary, "` = ?">> end, WhereKeys), + WhereSql = iolist_to_binary(lists:join(<<" AND ">>, WhereKeys1)), + + Params = SetVals ++ WhereVals, + + Sql = <<"UPDATE ", Table/binary, " SET ", SetSql/binary, " WHERE ", WhereSql/binary>>, + lager:debug("[mysql_client] update sql is: ~p, params: ~p", [Sql, Params]), + case mysql:query(ConnPid, Sql, Params) of + ok -> + AffectedRows = mysql:affected_rows(ConnPid), + {ok, AffectedRows}; + Error -> + lager:error("[mysql_client] update sql: ~p, params: ~p, get a error: ~p", [Sql, Params, Error]), + Error + end. + +-spec kvs(Fields :: map() | list()) -> {Keys :: list(), Values :: list()}. +kvs(Fields) when is_map(Fields) -> + kvs(maps:to_list(Fields)); +kvs(Fields) when is_list(Fields) -> + {Keys0, Values0} = lists:foldl(fun({K, V}, {Acc0, Acc1}) -> {[K|Acc0], [V|Acc1]} end, {[], []}, Fields), + {lists:reverse(Keys0), lists:reverse(Values0)}. \ No newline at end of file diff --git a/apps/njau_bot/src/njau_bot.app.src b/apps/njau_bot/src/njau_bot.app.src index 250b2c8..b5047f0 100644 --- a/apps/njau_bot/src/njau_bot.app.src +++ b/apps/njau_bot/src/njau_bot.app.src @@ -10,6 +10,8 @@ cowboy, lager, jiffy, + poolboy, + mysql, parse_trans, public_key, kernel, diff --git a/apps/njau_bot/src/njau_bot_database.erl b/apps/njau_bot/src/njau_bot_database.erl new file mode 100644 index 0000000..8caeb48 --- /dev/null +++ b/apps/njau_bot/src/njau_bot_database.erl @@ -0,0 +1,84 @@ +%%%------------------------------------------------------------------- +%%% @author aresei +%%% @copyright (C) 2023, +%%% @doc +%%% +%%% @end +%%% Created : 16. 5月 2023 12:48 +%%%------------------------------------------------------------------- +-module(njau_bot_database). +-author("aresei"). + +-export([insert_equip/1, insert_store_info/1, insert_equip_status/1, insert_run_status/1, insert_order/1]). + +-spec insert_store_info(Fields :: map()) -> {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert_store_info(Fields = #{<<"storeId">> := StoreId, <<"name">> := Name, <<"active">> := Active, <<"address">> := Address, <<"updateTime">> := UpdateTime}) -> + Longitude = maps:get(<<"longitude">>, Fields, <<"">>), + Latitude = maps:get(<<"latitude">>, Fields, <<"">>), + + mysql_pool:insert(<<"store_info">>, #{ + <<"storeId">> => StoreId, + <<"name">> => Name, + <<"longitude">> => Longitude, + <<"latitude">> => Latitude, + <<"active">> => Active, + <<"address">> => Address, + <<"updateTime">> => UpdateTime + }, true). + +-spec insert_equip(Fields :: map()) -> {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert_equip(Fields = #{<<"equipId">> := EquipId, <<"equipValue">> := EquipValue, <<"eType">> := EType, <<"address">> := Address, <<"updateTime">> := UpdateTime}) -> + mysql_pool:insert(<<"equip">>, #{ + <<"equipId">> => EquipId, + <<"equipValue">> => EquipValue, + <<"storeId">> => maps:get(<<"storeId">>, Fields, 0), + <<"eType">> => EType, + <<"remark">> => maps:get(<<"remark">>, Fields, <<"">>), + <<"address">> => Address, + <<"updateTime">> => UpdateTime + }, true). + +-spec insert_run_status(Fields :: map()) -> {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert_run_status(Fields = #{<<"equipValue">> := EquipValue, <<"eType">> := EType, <<"status">> := Status, <<"storeId">> := StoreId, <<"updateTime">> := UpdateTime}) -> + mysql_pool:insert(<<"run_status">>, #{ + <<"equipValue">> => EquipValue, + <<"eType">> => EType, + <<"status">> => Status, + <<"num">> => maps:get(<<"num">>, Fields, 0), + <<"storeId">> => StoreId, + <<"updateTime">> => UpdateTime + }, true). + +-spec insert_equip_status(Fields :: map()) -> {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert_equip_status(#{<<"equipValue">> := EquipValue, <<"status">> := Status, <<"updateTime">> := UpdateTime}) -> + mysql_pool:insert(<<"equip_status">>, #{ + <<"equipValue">> => EquipValue, + <<"status">> => Status, + <<"updateTime">> => UpdateTime + }, true). + +-spec insert_order(Fields :: map()) -> {ok, InsertId :: integer()} | {error, Reason :: any()}. +insert_order(Fields = #{ + <<"outTradeNo">> := OutTradeNo, <<"orderAmount">> := OrderAmount, <<"createTime">> := CreateTime, <<"status">> := Status, + <<"equipValue">> := EquipValue, <<"eType">> := EType, + <<"storeId">> := StoreId, <<"storeName">> := StoreName}) -> + + mysql_pool:insert(<<"order">>, #{ + <<"outTradeNo">> => OutTradeNo, + <<"orderAmount">> => OrderAmount, + <<"serviceName">> => maps:get(<<"serviceName">>, Fields, <<"">>), + <<"userId">> => maps:get(<<"userId">>, Fields, 0), + <<"createTime">> => CreateTime, + <<"payFinishTime">> => maps:get(<<"payFinishTime">>, Fields, <<"0000-00-00 00:00:00">>), + <<"status">> => Status, + <<"equipValue">> => EquipValue, + <<"eType">> => EType, + <<"num">> => maps:get(<<"num">>, Fields, 0), + + <<"storeId">> => StoreId, + <<"storeName">> => StoreName, + + <<"refundOrderNo">> => maps:get(<<"refundOrderNo">>, Fields, <<"">>), + <<"refundTime">> => maps:get(<<"refundTime">>, Fields, <<"0000-00-00 00:00:00">>), + <<"refundAmount">> => maps:get(<<"refundAmount">>, Fields, 0) + }, true). \ No newline at end of file diff --git a/apps/njau_bot/src/njau_bot_sup.erl b/apps/njau_bot/src/njau_bot_sup.erl index eacf9b5..5afb0e1 100644 --- a/apps/njau_bot/src/njau_bot_sup.erl +++ b/apps/njau_bot/src/njau_bot_sup.erl @@ -37,6 +37,12 @@ init([]) -> modules => ['njau_bot_logger'] } ], - {ok, {SupFlags, ChildSpecs}}. + {ok, {SupFlags, pools() ++ ChildSpecs}}. %% internal functions + +pools() -> + {ok, Pools} = application:get_env(njau_bot, pools), + lists:map(fun({Name, PoolArgs, WorkerArgs}) -> + poolboy:child_spec(Name, [{name, {local, Name}}|PoolArgs], WorkerArgs) + end, Pools). diff --git a/config/sys.config b/config/sys-dev.config similarity index 80% rename from config/sys.config rename to config/sys-dev.config index 6e9772e..c486a24 100644 --- a/config/sys.config +++ b/config/sys-dev.config @@ -8,6 +8,23 @@ {backlog, 10240} ]}, + {pools, [ + %% mysql连接池配置 + {mysql_bot, + [{size, 10}, {max_overflow, 20}, {worker_module, mysql}], + [ + {host, "39.98.184.67"}, + {port, 3306}, + {user, "nannonguser"}, + {connect_mode, synchronous}, + {keep_alive, true}, + {password, "nannong@Fe7w"}, + {database, "njau_bot"}, + {queries, [<<"set names utf8">>]} + ] + } + ]}, + {token, "aB3$dEfGhiJkLmNoPqRsTuVwXyZ!@#4f5e6d7c8b9a0f1e2d"} ]}, diff --git a/config/sys-prod.config b/config/sys-prod.config new file mode 100644 index 0000000..31acdb7 --- /dev/null +++ b/config/sys-prod.config @@ -0,0 +1,65 @@ +[ + {njau_bot, [ + + {http_server, [ + {port, 18085}, + {acceptors, 500}, + {max_connections, 10240}, + {backlog, 10240} + ]}, + + {pools, [ + %% mysql连接池配置 + {mysql_bot, + [{size, 10}, {max_overflow, 20}, {worker_module, mysql}], + [ + {host, {172, 30, 37, 231}}, + {port, 3306}, + {user, "njaubot"}, + {connect_mode, synchronous}, + {keep_alive, true}, + {password, "v238xo@J1c8WGu"}, + {database, "njau_bot"}, + {queries, [<<"set names utf8">>]} + ] + } + ]}, + + {token, "aB3$dEfGhiJkLmNoPqRsTuVwXyZ!@#4f5e6d7c8b9a0f1e2d"} + ]}, + + %% 系统日志配置,系统日志为lager, 支持日志按日期自动分割 + {lager, [ + {colored, true}, + %% Whether to write a crash log, and where. Undefined means no crash logger. + {crash_log, "trade_hub.crash.log"}, + %% Maximum size in bytes of events in the crash log - defaults to 65536 + {crash_log_msg_size, 65536}, + %% Maximum size of the crash log in bytes, before its rotated, set + %% to 0 to disable rotation - default is 0 + {crash_log_size, 10485760}, + %% What time to rotate the crash log - default is no time + %% rotation. See the README for a description of this format. + {crash_log_date, "$D0"}, + %% Number of rotated crash logs to keep, 0 means keep only the + %% current one - default is 0 + {crash_log_count, 5}, + %% Whether to redirect error_logger messages into lager - defaults to true + {error_logger_redirect, true}, + + %% How big the gen_event mailbox can get before it is switched into sync mode + {async_threshold, 20}, + %% Switch back to async mode, when gen_event mailbox size decrease from `async_threshold' + %% to async_threshold - async_threshold_window + {async_threshold_window, 5}, + + {handlers, [ + %% debug | info | warning | error, 日志级别 + {lager_console_backend, debug}, + {lager_file_backend, [{file, "debug.log"}, {level, debug}, {size, 314572800}]}, + {lager_file_backend, [{file, "notice.log"}, {level, notice}, {size, 314572800}]}, + {lager_file_backend, [{file, "error.log"}, {level, error}, {size, 314572800}]}, + {lager_file_backend, [{file, "info.log"}, {level, info}, {size, 314572800}]} + ]} + ]} +]. diff --git a/docs/table.sql b/docs/table.sql new file mode 100644 index 0000000..214ebfe --- /dev/null +++ b/docs/table.sql @@ -0,0 +1,70 @@ +CREATE TABLE `store_info` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `storeId` bigint(20) unsigned NOT NULL COMMENT '场地ID', + `name` varchar(255) NOT NULL DEFAULT '' COMMENT '场地名称', + `longitude` varchar(20) NOT NULL DEFAULT '' COMMENT '场地经度', + `latitude` varchar(10) NOT NULL DEFAULT '' COMMENT '场地纬度', + `active` varchar(10) DEFAULT '' COMMENT '状态,Y有效 N无效', + `address` varchar(255) DEFAULT '' COMMENT '详细地址', + `updateTime` datetime NOT NULL COMMENT '最新更新时间,格式: yyyy-MM-dd HH:mm:ss', + PRIMARY KEY (`id`), + KEY (`storeId`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `equip` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `equipId` bigint(20) unsigned NOT NULL COMMENT '设备id', + `equipValue` varchar(100) NOT NULL DEFAULT '' COMMENT '设备编号', + `storeId` bigint(20) unsigned NOT NULL COMMENT '场地ID', + `eType` varchar(10) NOT NULL DEFAULT '' COMMENT '设备类型:XYJ 洗衣机 HGJ 烘干机 XXJ 洗鞋机 CFT 吹风机', + `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '设备类型:XYJ 洗衣机 HGJ 烘干机 XXJ 洗鞋机 CFT 吹风机', + `address` varchar(255) DEFAULT '' COMMENT '详细地址', + `updateTime` datetime NOT NULL COMMENT '最新更新时间,格式: yyyy-MM-dd HH:mm:ss', + PRIMARY KEY (`id`), + KEY (`equipId`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `run_status` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `equipValue` varchar(100) NOT NULL DEFAULT '' COMMENT '设备编号', + `eType` varchar(10) NOT NULL DEFAULT '' COMMENT '设备类型:XYJ 洗衣机 HGJ 烘干机 XXJ 洗鞋机 CFT 吹风机', + `status` smallint(1) unsigned NOT NULL COMMENT '状态 1空闲 2工作中 3故障 4暂停', + `num` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '端口号,仅吹风机有', + `storeId` bigint(20) unsigned NOT NULL COMMENT '设备当前场地id', + `updateTime` datetime NOT NULL COMMENT '最新更新时间,格式: yyyy-MM-dd HH:mm:ss', + PRIMARY KEY (`id`), + KEY (`equipId`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `equip_status` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `equipValue` varchar(100) NOT NULL DEFAULT '' COMMENT '设备编号', + `status` smallint(1) unsigned NOT NULL COMMENT '状态 1: 在线, 0: 离线', + `updateTime` datetime NOT NULL COMMENT '最新更新时间,格式: yyyy-MM-dd HH:mm:ss', + PRIMARY KEY (`id`), + KEY (`equipValue`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `order` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `outTradeNo` varchar(100) NOT NULL DEFAULT '' COMMENT '订单号', + `orderAmount` decimal(11,2) DEFAULT NULL COMMENT '订单金额', + `serviceName` varchar(100) NOT NULL DEFAULT '' COMMENT '套餐名称', + `userId` bigint(20) unsigned NOT NULL DEFAULT 0 COMMENT '用户ID', + + `createTime` datetime NOT NULL COMMENT '订单创建时间,格式: yyyy-MM-dd HH:mm:ss', + `payFinishTime` datetime NOT NULL COMMENT '订单支付完成时间,格式: yyyy-MM-dd HH:mm:ss', + `status` smallint unsigned NOT NULL COMMENT '订单状态 1未支付 2已支付 3.退款中 4已退款', + + `equipValue` varchar(100) NOT NULL DEFAULT '' COMMENT '设备编号', + `eType` varchar(10) NOT NULL DEFAULT '' COMMENT '设备类型:XYJ 洗衣机 HGJ 烘干机 XXJ 洗鞋机 CFT 吹风机', + `num` int(10) unsigned NOT NULL DEFAULT 0 COMMENT '端口号,仅吹风机有', + `storeId` bigint(20) unsigned NOT NULL COMMENT '设备当前场地id', + `storeName` varchar(255) NOT NULL DEFAULT '' COMMENT '场地名称', + + `refundOrderNo` varchar(255) NOT NULL DEFAULT '' COMMENT '退款订单号', + `refundTime` datetime NOT NULL COMMENT '退款时间,格式: yyyy-MM-dd HH:mm:ss', + `refundAmount` decimal(11,2) DEFAULT NULL COMMENT '退款金额', + PRIMARY KEY (`id`), + KEY (`outTradeNo`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; \ No newline at end of file diff --git a/rebar.config b/rebar.config index 4964d79..dbe4f03 100644 --- a/rebar.config +++ b/rebar.config @@ -4,6 +4,8 @@ {sync, ".*", {git, "https://github.com/rustyio/sync.git", {branch, "master"}}}, {cowboy, ".*", {git, "https://github.com/ninenines/cowboy.git", {tag, "2.10.0"}}}, {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "1.1.1"}}}, + {poolboy, ".*", {git, "https://github.com/devinus/poolboy.git", {tag, "1.5.1"}}}, + {mysql, ".*", {git, "https://github.com/mysql-otp/mysql-otp", {tag, "1.8.0"}}}, {parse_trans, ".*", {git, "https://github.com/uwiger/parse_trans", {tag, "3.0.0"}}}, {lager, ".*", {git,"https://github.com/erlang-lager/lager.git", {tag, "3.9.2"}}} ]}. diff --git a/rebar.lock b/rebar.lock index d9d389a..aa39890 100644 --- a/rebar.lock +++ b/rebar.lock @@ -25,10 +25,18 @@ 0}, {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},1}, {<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.2.0">>},1}, + {<<"mysql">>, + {git,"https://github.com/mysql-otp/mysql-otp", + {ref,"caf5ff96c677a8fe0ce6f4082bc036c8fd27dd62"}}, + 0}, {<<"parse_trans">>, {git,"https://github.com/uwiger/parse_trans", {ref,"6f3645afb43c7c57d61b54ef59aecab288ce1013"}}, 0}, + {<<"poolboy">>, + {git,"https://github.com/devinus/poolboy.git", + {ref,"3bb48a893ff5598f7c73731ac17545206d259fac"}}, + 0}, {<<"ranch">>, {git,"https://github.com/ninenines/ranch", {ref,"a692f44567034dacf5efcaa24a24183788594eb7"}},