mirror of
https://gitee.com/dgiiot/dgiot.git
synced 2024-12-05 05:37:40 +08:00
fix: modbus_decoder
This commit is contained in:
parent
95368fafd5
commit
f8589991f5
@ -461,8 +461,7 @@ modbus_tcp_decoder(ProductId, TransactionId, Address, Data, Acc1) ->
|
|||||||
NewAddress = Sh * 256 + Sl,
|
NewAddress = Sh * 256 + Sl,
|
||||||
case {TransactionId, Address} of
|
case {TransactionId, Address} of
|
||||||
{NewSlaveid, NewAddress} ->
|
{NewSlaveid, NewAddress} ->
|
||||||
%% case format_value(Data, X, Props) of
|
case format_value(Data, X, Props) of
|
||||||
case format_value(Data, X) of
|
|
||||||
{Value, _Rest} ->
|
{Value, _Rest} ->
|
||||||
Acc#{Identifier => Value};
|
Acc#{Identifier => Value};
|
||||||
{map, Value, _Rest} ->
|
{map, Value, _Rest} ->
|
||||||
@ -486,20 +485,24 @@ modbus_decoder(ProductId, SlaveId, Address, Data, Acc1) ->
|
|||||||
case X of
|
case X of
|
||||||
#{<<"identifier">> := Identifier,
|
#{<<"identifier">> := Identifier,
|
||||||
<<"dataForm">> := #{
|
<<"dataForm">> := #{
|
||||||
|
<<"strategy">> := Strategy,
|
||||||
<<"slaveid">> := OldSlaveid,
|
<<"slaveid">> := OldSlaveid,
|
||||||
<<"address">> := OldAddress,
|
<<"address">> := OldAddress,
|
||||||
<<"protocol">> := <<"modbus">>
|
<<"protocol">> := <<"modbus">>
|
||||||
}} ->
|
}} when Strategy =/= <<"计算值"/utf8>> ->
|
||||||
<<H:8, L:8>> = dgiot_utils:hex_to_binary(modbus_rtu:is16(OldSlaveid)),
|
<<H:8, L:8>> = dgiot_utils:hex_to_binary(modbus_rtu:is16(OldSlaveid)),
|
||||||
<<Sh:8, Sl:8>> = dgiot_utils:hex_to_binary(modbus_rtu:is16(OldAddress)),
|
<<Sh:8, Sl:8>> = dgiot_utils:hex_to_binary(modbus_rtu:is16(OldAddress)),
|
||||||
NewSlaveid = H * 256 + L,
|
NewSlaveid = H * 256 + L,
|
||||||
NewAddress = Sh * 256 + Sl,
|
NewAddress = Sh * 256 + Sl,
|
||||||
case {SlaveId, Address} of
|
case {SlaveId, Address} of
|
||||||
{NewSlaveid, NewAddress} ->
|
{NewSlaveid, NewAddress} ->
|
||||||
case format_value(Data, X) of
|
case format_value(Data, X, Props) of
|
||||||
|
{map, Value} ->
|
||||||
|
maps:merge(Acc, Value);
|
||||||
{Value, _Rest} ->
|
{Value, _Rest} ->
|
||||||
Acc#{Identifier => Value};
|
Acc#{Identifier => Value};
|
||||||
_ -> Acc
|
_A ->
|
||||||
|
Acc
|
||||||
end;
|
end;
|
||||||
_ ->
|
_ ->
|
||||||
Acc
|
Acc
|
||||||
@ -540,30 +543,64 @@ modbus_encoder(ProductId, SlaveId, Address, Value) ->
|
|||||||
%% 0x78 | 0x56 | 0x34 | 0x12
|
%% 0x78 | 0x56 | 0x34 | 0x12
|
||||||
|
|
||||||
format_value(Buff, #{
|
format_value(Buff, #{
|
||||||
<<"dataType">> := #{<<"type">> := <<"geopoint">>, <<"gpstype">> := <<"NMEA0183">>}}) ->
|
<<"dataType">> := #{<<"type">> := <<"geopoint">>, <<"gpstype">> := <<"NMEA0183">>}}, _Props) ->
|
||||||
{Longitude, Latitude} = dgiot_gps:nmea0183_frame(Buff),
|
{Longitude, Latitude} = dgiot_gps:nmea0183_frame(Buff),
|
||||||
{<<Longitude/binary, "_", Latitude/binary>>, <<"Rest">>};
|
{<<Longitude/binary, "_", Latitude/binary>>, <<"Rest">>};
|
||||||
|
|
||||||
format_value(Buff, #{
|
format_value(Buff, #{
|
||||||
<<"accessMode">> := <<"rw">>,
|
<<"accessMode">> := <<"rw">>,
|
||||||
<<"dataForm">> := DataForm} = X) ->
|
<<"dataForm">> := DataForm} = X, _Props) ->
|
||||||
format_value(Buff, X#{<<"accessMode">> => <<"r">>,
|
format_value(Buff, X#{<<"accessMode">> => <<"r">>,
|
||||||
<<"dataForm">> => DataForm#{<<"data">> => byte_size(Buff)}
|
<<"dataForm">> => DataForm#{<<"data">> => byte_size(Buff)}
|
||||||
});
|
}, _Props);
|
||||||
|
|
||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"identifier">> := BitIdentifier,
|
||||||
<<"data">> := Len,
|
<<"dataForm">> := #{
|
||||||
<<"originaltype">> := <<"bit">>
|
<<"originaltype">> := <<"bit">>
|
||||||
}}) ->
|
}}, Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
Values =
|
||||||
Size = max(2, IntLen) * 8,
|
lists:foldl(fun(X, Acc) ->
|
||||||
<<Value:Size, Rest/binary>> = Buff,
|
case X of
|
||||||
{Value, Rest};
|
#{<<"identifier">> := Identifier,
|
||||||
|
<<"dataForm">> := #{
|
||||||
|
<<"slaveid">> := BitIdentifier,
|
||||||
|
<<"address">> := Offset,
|
||||||
|
<<"data">> := Len,
|
||||||
|
<<"protocol">> := <<"modbus">>,
|
||||||
|
<<"strategy">> := <<"计算值"/utf8>>
|
||||||
|
}} ->
|
||||||
|
IntOffset = dgiot_utils:to_int(Offset),
|
||||||
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
|
Value =
|
||||||
|
case IntOffset of
|
||||||
|
0 ->
|
||||||
|
<<V:IntLen/binary, _/binary>> = Buff,
|
||||||
|
case format_value(V, X, Props) of
|
||||||
|
{Value1, _Rest} ->
|
||||||
|
Value1;
|
||||||
|
_ ->
|
||||||
|
V
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
<<_:IntOffset/binary, V:IntLen/binary, _/binary>> = Buff,
|
||||||
|
case format_value(V, X, Props) of
|
||||||
|
{Value1, _Rest} ->
|
||||||
|
Value1;
|
||||||
|
_ ->
|
||||||
|
V
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
Acc#{Identifier => Value};
|
||||||
|
_ ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, #{}, Props),
|
||||||
|
{map, Values};
|
||||||
|
|
||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"short16_AB">>
|
<<"originaltype">> := <<"short16_AB">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(2, IntLen) * 8,
|
Size = max(2, IntLen) * 8,
|
||||||
<<Value:Size/signed-big-integer, Rest/binary>> = Buff,
|
<<Value:Size/signed-big-integer, Rest/binary>> = Buff,
|
||||||
@ -572,7 +609,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"short16_BA">>
|
<<"originaltype">> := <<"short16_BA">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(2, IntLen) * 8,
|
Size = max(2, IntLen) * 8,
|
||||||
<<Value:Size/signed-little-integer, Rest/binary>> = Buff,
|
<<Value:Size/signed-little-integer, Rest/binary>> = Buff,
|
||||||
@ -581,7 +618,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"ushort16_AB">>
|
<<"originaltype">> := <<"ushort16_AB">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(2, IntLen) * 8,
|
Size = max(2, IntLen) * 8,
|
||||||
<<Value:Size/unsigned-big-integer, Rest/binary>> = Buff,
|
<<Value:Size/unsigned-big-integer, Rest/binary>> = Buff,
|
||||||
@ -590,7 +627,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"ushort16_BA">>
|
<<"originaltype">> := <<"ushort16_BA">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(2, IntLen) * 8,
|
Size = max(2, IntLen) * 8,
|
||||||
<<Value:Size/unsigned-little-integer, Rest/binary>> = Buff,
|
<<Value:Size/unsigned-little-integer, Rest/binary>> = Buff,
|
||||||
@ -599,7 +636,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"long32_ABCD">>
|
<<"originaltype">> := <<"long32_ABCD">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(4, IntLen) * 8,
|
Size = max(4, IntLen) * 8,
|
||||||
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
||||||
@ -609,7 +646,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"long32_CDAB">>
|
<<"originaltype">> := <<"long32_CDAB">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(4, IntLen) * 8,
|
Size = max(4, IntLen) * 8,
|
||||||
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
||||||
@ -619,7 +656,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"ulong32_ABCD">>
|
<<"originaltype">> := <<"ulong32_ABCD">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(4, IntLen) * 8,
|
Size = max(4, IntLen) * 8,
|
||||||
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
||||||
@ -629,7 +666,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"ulong32_CDAB">>
|
<<"originaltype">> := <<"ulong32_CDAB">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(4, IntLen) * 8,
|
Size = max(4, IntLen) * 8,
|
||||||
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
||||||
@ -639,7 +676,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"float32_ABCD">>
|
<<"originaltype">> := <<"float32_ABCD">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(4, IntLen) * 8,
|
Size = max(4, IntLen) * 8,
|
||||||
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
||||||
@ -649,7 +686,7 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
format_value(Buff, #{<<"dataForm">> := #{
|
format_value(Buff, #{<<"dataForm">> := #{
|
||||||
<<"data">> := Len,
|
<<"data">> := Len,
|
||||||
<<"originaltype">> := <<"float32_CDAB">>
|
<<"originaltype">> := <<"float32_CDAB">>
|
||||||
}}) ->
|
}}, _Props) ->
|
||||||
IntLen = dgiot_utils:to_int(Len),
|
IntLen = dgiot_utils:to_int(Len),
|
||||||
Size = max(4, IntLen) * 8,
|
Size = max(4, IntLen) * 8,
|
||||||
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
<<H:2/binary, L:2/binary, Rest/binary>> = Buff,
|
||||||
@ -657,6 +694,6 @@ format_value(Buff, #{<<"dataForm">> := #{
|
|||||||
{Value, Rest};
|
{Value, Rest};
|
||||||
|
|
||||||
%% @todo 其它类型处理
|
%% @todo 其它类型处理
|
||||||
format_value(_, #{<<"identifier">> := Field}) ->
|
format_value(_, #{<<"identifier">> := Field}, _Props) ->
|
||||||
?LOG(info, "Field ~p", [Field]),
|
?LOG(info, "Field ~p", [Field]),
|
||||||
throw({field_error, <<Field/binary, " is not validate">>}).
|
throw({field_error, <<Field/binary, " is not validate">>}).
|
||||||
|
@ -114,7 +114,7 @@ handle_message({sync_parse, Args, ObjectId}, State) ->
|
|||||||
#{<<"profile">> := _Profile, <<"devaddr">> := _Devaddr, <<"product">> := #{<<"objectId">> := _ProductId}} ->
|
#{<<"profile">> := _Profile, <<"devaddr">> := _Devaddr, <<"product">> := #{<<"objectId">> := _ProductId}} ->
|
||||||
handle_message({sync_parse, Args}, State);
|
handle_message({sync_parse, Args}, State);
|
||||||
#{<<"profile">> := Profile} ->
|
#{<<"profile">> := Profile} ->
|
||||||
io:format("~s ~p ObjectId = ~p.~n", [?FILE, ?LINE, ObjectId]),
|
%% io:format("~s ~p ObjectId = ~p.~n", [?FILE, ?LINE, ObjectId]),
|
||||||
case dgiot_device:lookup(dgiot_utils:to_binary(ObjectId)) of
|
case dgiot_device:lookup(dgiot_utils:to_binary(ObjectId)) of
|
||||||
{ok, #{<<"devaddr">> := Devaddr, <<"productid">> := ProductId}} ->
|
{ok, #{<<"devaddr">> := Devaddr, <<"productid">> := ProductId}} ->
|
||||||
NewArgs = jsx:encode(#{<<"profile">> => Profile, <<"devaddr">> => Devaddr, <<"product">> => #{<<"objectId">> => ProductId}}),
|
NewArgs = jsx:encode(#{<<"profile">> => Profile, <<"devaddr">> => Devaddr, <<"product">> => #{<<"objectId">> => ProductId}}),
|
||||||
@ -133,7 +133,7 @@ handle_message({sync_parse, Args, ObjectId}, State) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
handle_message({sync_parse, Args}, State) ->
|
handle_message({sync_parse, Args}, State) ->
|
||||||
io:format("~s ~p Args = ~p.~n", [?FILE, ?LINE, jsx:decode(Args, [{labels, binary}, return_maps])]),
|
%% io:format("~s ~p Args = ~p.~n", [?FILE, ?LINE, jsx:decode(Args, [{labels, binary}, return_maps])]),
|
||||||
case jsx:decode(Args, [{labels, binary}, return_maps]) of
|
case jsx:decode(Args, [{labels, binary}, return_maps]) of
|
||||||
#{<<"profile">> := Profile, <<"devaddr">> := Devaddr, <<"product">> := #{<<"objectId">> := ProductId}} = Arg ->
|
#{<<"profile">> := Profile, <<"devaddr">> := Devaddr, <<"product">> := #{<<"objectId">> := ProductId}} = Arg ->
|
||||||
Sessiontoken = maps:get(<<"sessiontoken">>, Arg, <<"">>),
|
Sessiontoken = maps:get(<<"sessiontoken">>, Arg, <<"">>),
|
||||||
|
@ -146,7 +146,7 @@ handle_info(retry, State) ->
|
|||||||
handle_info({deliver, _, Msg}, #task{tid = Channel, dis = Dis, product = ProductId, devaddr = DevAddr, ack = Ack, que = Que} = State) when length(Que) == 0 ->
|
handle_info({deliver, _, Msg}, #task{tid = Channel, dis = Dis, product = ProductId, devaddr = DevAddr, ack = Ack, que = Que} = State) when length(Que) == 0 ->
|
||||||
Payload = jsx:decode(dgiot_mqtt:get_payload(Msg), [return_maps]),
|
Payload = jsx:decode(dgiot_mqtt:get_payload(Msg), [return_maps]),
|
||||||
dgiot_bridge:send_log(Channel, ProductId, DevAddr, "~s ~p ~ts: ~ts ", [?FILE, ?LINE, unicode:characters_to_list(dgiot_mqtt:get_topic(Msg)), unicode:characters_to_list(dgiot_mqtt:get_payload(Msg))]),
|
dgiot_bridge:send_log(Channel, ProductId, DevAddr, "~s ~p ~ts: ~ts ", [?FILE, ?LINE, unicode:characters_to_list(dgiot_mqtt:get_topic(Msg)), unicode:characters_to_list(dgiot_mqtt:get_payload(Msg))]),
|
||||||
NewAck = dgiot_task:get_collection(ProductId, Dis, Payload, Ack),
|
NewAck = dgiot_task:get_collection(ProductId, Dis, Payload, maps:merge(Ack, Payload)),
|
||||||
dgiot_metrics:inc(dgiot_task, <<"task_recv">>, 1),
|
dgiot_metrics:inc(dgiot_task, <<"task_recv">>, 1),
|
||||||
{noreply, get_next_pn(State#task{ack = NewAck})};
|
{noreply, get_next_pn(State#task{ack = NewAck})};
|
||||||
|
|
||||||
@ -246,8 +246,8 @@ save_td(#task{app = _App, tid = Channel, product = ProductId, devaddr = DevAddr,
|
|||||||
0 ->
|
0 ->
|
||||||
pass;
|
pass;
|
||||||
_ ->
|
_ ->
|
||||||
dgiot_bridge:send_log(Channel, ProductId, DevAddr, "save_td=> ~s ~p ~p: ~ts ", [?FILE, ?LINE, ProductId, unicode:characters_to_list(jsx:encode(Ack))]),
|
|
||||||
Data = dgiot_task:get_calculated(ProductId, Ack),
|
Data = dgiot_task:get_calculated(ProductId, Ack),
|
||||||
|
dgiot_bridge:send_log(Channel, ProductId, DevAddr, "save_td=> ~s ~p ~p: ~ts ", [?FILE, ?LINE, ProductId, unicode:characters_to_list(jsx:encode(Data))]),
|
||||||
case length(maps:to_list(Data)) of
|
case length(maps:to_list(Data)) of
|
||||||
0 ->
|
0 ->
|
||||||
pass;
|
pass;
|
||||||
|
Loading…
Reference in New Issue
Block a user