feat: Default latitude and longitude

This commit is contained in:
dawnwinterLiu 2022-06-23 19:57:34 +08:00
parent a227038270
commit 28acc41c61
4 changed files with 20 additions and 238 deletions

View File

@ -282,7 +282,7 @@ to_frame(ProductId, Msg) ->
format_product(#{<<"objectId">> := ProductId} = Product) ->
Thing = maps:get(<<"thing">>, Product, #{}),
Props = maps:get(<<"properties">>, Thing, []),
Keys = [<<"ACL">>, <<"name">>, <<"devType">>, <<"status">>, <<"channel">>, <<"content">>, <<"profile">>, <<"nodeType">>, <<"dynamicReg">>, <<"topics">>, <<"productSecret">>],
Keys = [<<"ACL">>, <<"name">>, <<"config">>, <<"devType">>, <<"status">>, <<"channel">>, <<"content">>, <<"profile">>, <<"nodeType">>, <<"dynamicReg">>, <<"topics">>, <<"productSecret">>],
Map = maps:with(Keys, Product),
Map#{
<<"productId">> => ProductId,

View File

@ -84,15 +84,24 @@ post(Device) ->
ProductId = maps:get(<<"objectId">>, Product),
DeviceSecret = maps:get(<<"deviceSecret">>, Device, <<"oioojn">>),
DeviceId = maps:get(<<"objectId">>, Device, dgiot_parse_id:get_deviceid(ProductId, Devaddr)),
{Data, Location, Address} =
case dgiot_product:lookup_prod(ProductId) of
{ok, ProductInfo} ->
Data = maps:with([<<"profile">>, <<"content">>], ProductInfo),
dgiot_parse:update_object(<<"Device">>, DeviceId, Data);
Data1 = maps:with([<<"profile">>, <<"content">>], ProductInfo),
case maps:find(<<"config">>, #{}) of
{ok, #{<<"location">> := Location1, <<"address">> := Address1}} ->
{Data1, Location1, Address1};
_ ->
pass
{Data1, #{<<"__type">> => <<"GeoPoint">>, <<"longitude">> => 120.065463, <<"latitude">> => 30.368707}, <<>>}
end;
_ ->
{#{}, #{<<"__type">> => <<"GeoPoint">>, <<"longitude">> => 120.065463, <<"latitude">> => 30.368707}, <<>>}
end,
dgiot_parse:update_object(<<"Device">>, DeviceId, Data#{<<"location">> => maps:get(<<"location">>, Device, Location), <<"address">> => maps:get(<<"address">>, Device, Address)}),
#{<<"longitude">> := Longitude, <<"latitude">> := Latitude} =
maps:get(<<"location">>, Device, #{<<"__type">> => <<"GeoPoint">>, <<"longitude">> => 120.161324, <<"latitude">> => 30.262441}),
maps:get(<<"location">>, Device, Location),
Status =
case maps:get(<<"status">>, Device, <<"OFFLINE">>) of
<<"OFFLINE">> -> false;

View File

@ -75,22 +75,6 @@
zh => <<"填写正则表达式匹配login报文, 9C-A5标识设备类型**-**-**-**为设备地址,中杆会自动去除"/utf8>>
}
},
<<"modbustype">> => #{
order => 4,
type => string,
required => true,
default => #{<<"value">> => <<"modbusrtu">>, <<"label">> => <<"Modbus RTU">>},
enum => [
#{<<"value">> => <<"modbusrtu">>, <<"label">> => <<"Modbus RTU">>},
#{<<"value">> => <<"modbustcp">>, <<"label">> => <<"Modbus TCP">>}
],
title => #{
zh => <<"Modbus种类"/utf8>>
},
description => #{
zh => <<"Modbus种类"/utf8>>
}
},
<<"dtutype">> => #{
order => 5,
type => string,
@ -129,7 +113,7 @@ init(?TYPE, ChannelId, #{
<<"regular">> := Regular,
<<"product">> := Products,
<<"dtutype">> := Dtutype
} = Args) ->
} = _Args) ->
{ProdcutId, App} =
case get_app(Products) of
[{ProdcutId1, App1} | _] ->
@ -149,13 +133,7 @@ init(?TYPE, ChannelId, #{
product = ProdcutId,
dtutype = Dtutype
},
%% dgiot_data:insert({ChannelId, heartbeat}, {Heartbeat, Port}),
case maps:get(<<"modbustype">>, Args, <<"modbusrtu">>) of
<<"modbustcp">> ->
{ok, State, dgiot_modbustcp_tcp:start(Port, State)};
_ ->
{ok, State, dgiot_modbusrtu_tcp:start(Port, State)}
end;
{ok, State, dgiot_modbusrtu_tcp:start(Port, State)};
init(?TYPE, _ChannelId, _Args) ->

View File

@ -1,205 +0,0 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2020-2021 DGIOT Technologies Co., Ltd. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%--------------------------------------------------------------------
-module(dgiot_modbustcp_tcp).
-author("stoneliu").
-include("dgiot_modbus.hrl").
-include_lib("dgiot/include/dgiot_socket.hrl").
-include_lib("dgiot/include/logger.hrl").
-define(MAX_BUFF_SIZE, 1024).
-export([
get_deviceid/2,
start/2
]).
%% TCP callback
-export([init/1, handle_info/2, handle_cast/2, handle_call/3, terminate/2, code_change/3]).
start(Port, State) ->
dgiot_tcp_server:child_spec(?MODULE, dgiot_utils:to_int(Port), State).
%% =======================
%% {ok, State} | {stop, Reason}
%%init(TCPState) ->
%% erlang:send_after(5 * 1000, self(), login),.
%% {ok, TCPState}.
init(#tcp{state = #state{id = ChannelId}} = TCPState) ->
case dgiot_bridge:get_products(ChannelId) of
{ok, _TYPE, _ProductIds} ->
{ok, TCPState};
{error, not_find} ->
{stop, not_find_channel}
end.
%% 9C A5 25 CD 00 DB
%% 11 04 02 06 92 FA FE
handle_info({tcp, Buff}, #tcp{socket = Socket, state = #state{id = ChannelId, devaddr = <<>>, head = Head, len = Len, product = ProductId, dtutype = Dtutype} = State} = TCPState) ->
DTUIP = dgiot_utils:get_ip(Socket),
DtuAddr = dgiot_utils:binary_to_hex(Buff),
List = dgiot_utils:to_list(DtuAddr),
List1 = dgiot_utils:to_list(Buff),
case re:run(DtuAddr, Head, [{capture, first, list}]) of
{match, [Head]} when length(List) == Len ->
DeviceId = dgiot_parse_id:get_deviceid(ProductId, DtuAddr),
create_device(DeviceId, ProductId, DtuAddr, DTUIP, Dtutype),
dgiot_bridge:send_log(ChannelId, ProductId, DtuAddr, "~s ~p DTU login DtuAddr:~p", [?FILE, ?LINE, DtuAddr]),
Topic = <<"$dg/device/", ProductId/binary, "/", DtuAddr/binary, "/profile">>,
dgiot_mqtt:subscribe(Topic),
{noreply, TCPState#tcp{buff = <<>>, register = true, clientid = DeviceId, state = State#state{devaddr = DtuAddr, deviceId = DeviceId}}};
_Error ->
case re:run(Buff, Head, [{capture, first, list}]) of
{match, [Head]} when length(List1) == Len ->
DeviceId = dgiot_parse_id:get_deviceid(ProductId, Buff),
create_device(DeviceId, ProductId, Buff, DTUIP, Dtutype),
Topic = <<"$dg/device/", ProductId/binary, "/", Buff/binary, "/profile">>,
dgiot_bridge:send_log(ChannelId, ProductId, Buff, "~s ~p DTU login DtuAddr:~p", [?FILE, ?LINE, Buff]),
dgiot_mqtt:subscribe(Topic),
{noreply, TCPState#tcp{buff = <<>>, register = true, clientid = DeviceId, state = State#state{devaddr = Buff}}};
Error1 ->
?LOG(info, "Error1 ~p Buff ~p ", [Error1, dgiot_utils:to_list(Buff)]),
{noreply, TCPState#tcp{buff = <<>>}}
end
end;
handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId, devaddr = DtuAddr, env = #{product := ProductId, pn := Pn, di := Di}, product = DtuProductId} = State} = TCPState) ->
dgiot_bridge:send_log(ChannelId, ProductId, DtuAddr, "~s ~p DTU ~p recv ~p", [?FILE, ?LINE, DtuAddr, dgiot_utils:binary_to_hex(Buff)]),
<<H:8, L:8>> = dgiot_utils:hex_to_binary(modbus_tcp:is16(Di)),
<<Sh:8, Sl:8>> = dgiot_utils:hex_to_binary(modbus_tcp:is16(Pn)),
case modbus_tcp:parse_frame(Buff, #{}, #{
<<"dtuproduct">> => ProductId,
<<"channel">> => ChannelId,
<<"dtuaddr">> => DtuAddr,
<<"slaveId">> => Sh * 256 + Sl,
<<"address">> => H * 256 + L}) of
{_, Things} ->
NewTopic = <<"$dg/thing/", DtuProductId/binary, "/", DtuAddr/binary, "/properties/report">>,
dgiot_bridge:send_log(ChannelId, ProductId, DtuAddr, "~s ~p to task ~p ~ts ", [?FILE, ?LINE, NewTopic, unicode:characters_to_list(jsx:encode(Things))]),
DeviceId = dgiot_parse_id:get_deviceid(ProductId, DtuAddr),
Taskchannel = dgiot_product:get_taskchannel(ProductId),
dgiot_client:send(Taskchannel, DeviceId, NewTopic, Things);
Other ->
?LOG(info, "Other ~p", [Other]),
pass
end,
{noreply, TCPState#tcp{buff = <<>>, state = State#state{env = <<>>}}};
handle_info({deliver, _, Msg}, #tcp{state = #state{id = ChannelId} = State} = TCPState) ->
Payload = dgiot_mqtt:get_payload(Msg),
Topic = dgiot_mqtt:get_topic(Msg),
case jsx:is_json(Payload) of
true ->
case binary:split(Topic, <<$/>>, [global, trim]) of
[<<"$dg">>, <<"device">>, ProductId, DevAddr, <<"profile">>] ->
%%
Payloads = modbus_tcp:set_params(jsx:decode(Payload), ProductId, DevAddr),
lists:map(fun(X) ->
dgiot_tcp_server:send(TCPState, X)
end, Payloads),
{noreply, TCPState};
[<<"$dg">>, <<"device">>, ProductId, DevAddr, <<"properties">>] ->
case jsx:decode(Payload, [{labels, binary}, return_maps]) of
#{<<"slaveid">> := SlaveId, <<"address">> := Address} = DataSource ->
Data = modbus_tcp:to_frame(DataSource),
%% io:format("~s ~p Data = ~p.~n", [?FILE, ?LINE, dgiot_utils:to_hex(Data)]),
dgiot_bridge:send_log(ChannelId, ProductId, DevAddr, "Channel sends ~p to DTU ~p", [dgiot_utils:binary_to_hex(Data), DevAddr]),
dgiot_tcp_server:send(TCPState, Data),
{noreply, TCPState#tcp{state = State#state{env = #{product => ProductId, pn => SlaveId, di => Address}}}};
_ ->
{noreply, TCPState}
end;
_Other ->
?LOG(error, "_Other ~p", [_Other]),
{noreply, TCPState}
end;
false ->
case binary:split(Topic, <<$/>>, [global, trim]) of
[<<"$dg">>, <<"device">>, ProductId, DevAddr, <<"profile">>] ->
%%
Payloads = modbus_tcp:set_params(jsx:decode(Payload), ProductId, DevAddr),
lists:map(fun(X) ->
dgiot_tcp_server:send(TCPState, X)
end, Payloads),
{noreply, TCPState};
_ ->
{noreply, TCPState}
end
end;
%% {stop, TCPState} | {stop, Reason} | {ok, TCPState} | ok | stop
handle_info(_Info, TCPState) ->
?LOG(info, "TCPState ~p", [TCPState]),
{noreply, TCPState}.
handle_call(_Msg, _From, TCPState) ->
{reply, ok, TCPState}.
handle_cast(_Msg, TCPState) ->
{noreply, TCPState}.
terminate(_Reason, #tcp{state = #state{devaddr = DtuAddr, product = ProductId}} = _TCPState) ->
DeviceId = dgiot_parse_id:get_deviceid(ProductId, DtuAddr),
Taskchannel = dgiot_product:get_taskchannel(ProductId),
dgiot_task:del_pnque(DeviceId),
dgiot_client:stop(Taskchannel, DeviceId),
ok;
terminate(_Reason, _TCPState) ->
ok.
code_change(_OldVsn, TCPState, _Extra) ->
{ok, TCPState}.
get_deviceid(ProdcutId, DevAddr) ->
#{<<"objectId">> := DeviceId} =
dgiot_parse_id:get_objectid(<<"Device">>, #{<<"product">> => ProdcutId, <<"devaddr">> => DevAddr}),
DeviceId.
create_device(DeviceId, ProductId, DTUMAC, DTUIP, Dtutype) ->
case dgiot_product:lookup_prod(ProductId) of
{ok, #{<<"ACL">> := Acl, <<"devType">> := DevType}} ->
case dgiot_parse:get_object(<<"Device">>, DeviceId) of
{ok, #{<<"devaddr">> := _GWAddr}} ->
dgiot_parse:update_object(<<"Device">>, DeviceId, #{<<"ip">> => DTUIP, <<"status">> => <<"ONLINE">>}),
dgiot_task:save_pnque(ProductId, DTUMAC, ProductId, DTUMAC);
_ ->
dgiot_device:create_device(#{
<<"devaddr">> => DTUMAC,
<<"name">> => <<Dtutype/binary, DTUMAC/binary>>,
<<"ip">> => DTUIP,
<<"isEnable">> => true,
<<"product">> => ProductId,
<<"ACL">> => Acl,
<<"status">> => <<"ONLINE">>,
<<"location">> => #{<<"__type">> => <<"GeoPoint">>, <<"longitude">> => 120.161324, <<"latitude">> => 30.262441},
<<"brand">> => Dtutype,
<<"devModel">> => DevType
}),
dgiot_task:save_pnque(ProductId, DTUMAC, ProductId, DTUMAC)
end,
Productname =
case dgiot_parse:get_object(<<"Product">>, ProductId) of
{ok, #{<<"name">> := Productname1}} ->
Productname1;
_ ->
<<"">>
end,
?MLOG(info, #{<<"clientid">> => DeviceId, <<"devaddr">> => DTUMAC, <<"productid">> => ProductId, <<"productname">> => Productname, <<"devicename">> => <<Dtutype/binary, DTUMAC/binary>>, <<"status">> => <<"上线"/utf8>>}, ['device_statuslog']),
{DeviceId, DTUMAC};
_Error2 ->
%% ?LOG(info, "Error2 ~p ", [Error2]),
{<<>>, <<>>}
end.