diff --git a/apps/dgiot_modbus/src/modbus/modbus_rtu.erl b/apps/dgiot_modbus/src/modbus/modbus_rtu.erl index 92e1a0a0..6729e2a2 100644 --- a/apps/dgiot_modbus/src/modbus/modbus_rtu.erl +++ b/apps/dgiot_modbus/src/modbus/modbus_rtu.erl @@ -461,8 +461,7 @@ modbus_tcp_decoder(ProductId, TransactionId, Address, Data, Acc1) -> NewAddress = Sh * 256 + Sl, case {TransactionId, Address} of {NewSlaveid, NewAddress} -> -%% case format_value(Data, X, Props) of - case format_value(Data, X) of + case format_value(Data, X, Props) of {Value, _Rest} -> Acc#{Identifier => Value}; {map, Value, _Rest} -> @@ -486,20 +485,24 @@ modbus_decoder(ProductId, SlaveId, Address, Data, Acc1) -> case X of #{<<"identifier">> := Identifier, <<"dataForm">> := #{ + <<"strategy">> := Strategy, <<"slaveid">> := OldSlaveid, <<"address">> := OldAddress, <<"protocol">> := <<"modbus">> - }} -> + }} when Strategy =/= <<"计算值"/utf8>> -> <> = dgiot_utils:hex_to_binary(modbus_rtu:is16(OldSlaveid)), <> = dgiot_utils:hex_to_binary(modbus_rtu:is16(OldAddress)), NewSlaveid = H * 256 + L, NewAddress = Sh * 256 + Sl, case {SlaveId, Address} of {NewSlaveid, NewAddress} -> - case format_value(Data, X) of + case format_value(Data, X, Props) of + {map, Value} -> + maps:merge(Acc, Value); {Value, _Rest} -> Acc#{Identifier => Value}; - _ -> Acc + _A -> + Acc end; _ -> Acc @@ -540,30 +543,64 @@ modbus_encoder(ProductId, SlaveId, Address, Value) -> %% 0x78 | 0x56 | 0x34 | 0x12 format_value(Buff, #{ - <<"dataType">> := #{<<"type">> := <<"geopoint">>, <<"gpstype">> := <<"NMEA0183">>}}) -> + <<"dataType">> := #{<<"type">> := <<"geopoint">>, <<"gpstype">> := <<"NMEA0183">>}}, _Props) -> {Longitude, Latitude} = dgiot_gps:nmea0183_frame(Buff), {<>, <<"Rest">>}; format_value(Buff, #{ <<"accessMode">> := <<"rw">>, - <<"dataForm">> := DataForm} = X) -> + <<"dataForm">> := DataForm} = X, _Props) -> format_value(Buff, X#{<<"accessMode">> => <<"r">>, <<"dataForm">> => DataForm#{<<"data">> => byte_size(Buff)} - }); + }, _Props); -format_value(Buff, #{<<"dataForm">> := #{ - <<"data">> := Len, - <<"originaltype">> := <<"bit">> -}}) -> - IntLen = dgiot_utils:to_int(Len), - Size = max(2, IntLen) * 8, - <> = Buff, - {Value, Rest}; +format_value(Buff, #{<<"identifier">> := BitIdentifier, + <<"dataForm">> := #{ + <<"originaltype">> := <<"bit">> + }}, Props) -> + Values = + lists:foldl(fun(X, Acc) -> + case X of + #{<<"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 -> + <> = 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">> := #{ <<"data">> := Len, <<"originaltype">> := <<"short16_AB">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(2, IntLen) * 8, <> = Buff, @@ -572,7 +609,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"short16_BA">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(2, IntLen) * 8, <> = Buff, @@ -581,7 +618,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"ushort16_AB">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(2, IntLen) * 8, <> = Buff, @@ -590,7 +627,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"ushort16_BA">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(2, IntLen) * 8, <> = Buff, @@ -599,7 +636,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"long32_ABCD">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(4, IntLen) * 8, <> = Buff, @@ -609,7 +646,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"long32_CDAB">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(4, IntLen) * 8, <> = Buff, @@ -619,7 +656,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"ulong32_ABCD">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(4, IntLen) * 8, <> = Buff, @@ -629,7 +666,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"ulong32_CDAB">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(4, IntLen) * 8, <> = Buff, @@ -639,7 +676,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"float32_ABCD">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(4, IntLen) * 8, <> = Buff, @@ -649,7 +686,7 @@ format_value(Buff, #{<<"dataForm">> := #{ format_value(Buff, #{<<"dataForm">> := #{ <<"data">> := Len, <<"originaltype">> := <<"float32_CDAB">> -}}) -> +}}, _Props) -> IntLen = dgiot_utils:to_int(Len), Size = max(4, IntLen) * 8, <> = Buff, @@ -657,6 +694,6 @@ format_value(Buff, #{<<"dataForm">> := #{ {Value, Rest}; %% @todo 其它类型处理 -format_value(_, #{<<"identifier">> := Field}) -> +format_value(_, #{<<"identifier">> := Field}, _Props) -> ?LOG(info, "Field ~p", [Field]), throw({field_error, <>}). diff --git a/apps/dgiot_task/src/dgiot_profile_channel.erl b/apps/dgiot_task/src/dgiot_profile_channel.erl index fcc5b173..cb550652 100644 --- a/apps/dgiot_task/src/dgiot_profile_channel.erl +++ b/apps/dgiot_task/src/dgiot_profile_channel.erl @@ -114,7 +114,7 @@ handle_message({sync_parse, Args, ObjectId}, State) -> #{<<"profile">> := _Profile, <<"devaddr">> := _Devaddr, <<"product">> := #{<<"objectId">> := _ProductId}} -> handle_message({sync_parse, Args}, State); #{<<"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 {ok, #{<<"devaddr">> := Devaddr, <<"productid">> := ProductId}} -> NewArgs = jsx:encode(#{<<"profile">> => Profile, <<"devaddr">> => Devaddr, <<"product">> => #{<<"objectId">> => ProductId}}), @@ -133,7 +133,7 @@ handle_message({sync_parse, Args, ObjectId}, State) -> end; 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 #{<<"profile">> := Profile, <<"devaddr">> := Devaddr, <<"product">> := #{<<"objectId">> := ProductId}} = Arg -> Sessiontoken = maps:get(<<"sessiontoken">>, Arg, <<"">>), diff --git a/apps/dgiot_task/src/dgiot_task_worker.erl b/apps/dgiot_task/src/dgiot_task_worker.erl index 58f9e0eb..682fd175 100644 --- a/apps/dgiot_task/src/dgiot_task_worker.erl +++ b/apps/dgiot_task/src/dgiot_task_worker.erl @@ -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 -> 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))]), - 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), {noreply, get_next_pn(State#task{ack = NewAck})}; @@ -246,8 +246,8 @@ save_td(#task{app = _App, tid = Channel, product = ProductId, devaddr = DevAddr, 0 -> 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), + 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 0 -> pass;