mirror of
https://gitee.com/dgiiot/dgiot.git
synced 2024-12-02 12:18:30 +08:00
xinchuangwei
This commit is contained in:
parent
2b77a8673e
commit
3aefee0d5d
@ -240,7 +240,7 @@ save_notification(Ruleid, DevAddr, Payload) ->
|
||||
}
|
||||
},
|
||||
<<"content">> => Payload#{<<"_deviceid">> => DeviceId, <<"_productid">> => ProductId},
|
||||
<<"public">> => true,
|
||||
<<"public">> => false,
|
||||
<<"sender">> => #{
|
||||
<<"__type">> => <<"Pointer">>,
|
||||
<<"className">> => <<"_User">>,
|
||||
@ -276,7 +276,7 @@ save_notification(Ruleid, DevAddr, Payload) ->
|
||||
}
|
||||
},
|
||||
<<"content">> => Payload#{<<"_deviceid">> => DeviceId, <<"_productid">> => ProductId},
|
||||
<<"public">> => true,
|
||||
<<"public">> => false,
|
||||
<<"sender">> => #{
|
||||
<<"__type">> => <<"Pointer">>,
|
||||
<<"className">> => <<"_User">>,
|
||||
@ -302,6 +302,14 @@ save_notification(Ruleid, DevAddr, Payload) ->
|
||||
sendSubscribe(NotificationId, UserId) ->
|
||||
case dgiot_parse:get_object(<<"Notification">>, NotificationId) of
|
||||
{ok, #{<<"type">> := Type, <<"content">> := Content}} ->
|
||||
DeviceId = maps:get(<<"_deviceid">>, Content, <<"">>),
|
||||
DeviceName =
|
||||
case dgiot_parse:get_object(<<"Device">>, DeviceId) of
|
||||
{ok, #{<<"name">> := DeviceName1}} ->
|
||||
DeviceName1;
|
||||
_ ->
|
||||
<<"">>
|
||||
end,
|
||||
Result =
|
||||
case binary:split(Type, <<$_>>, [global, trim]) of
|
||||
[ProductId, AlertId] ->
|
||||
@ -320,7 +328,7 @@ sendSubscribe(NotificationId, UserId) ->
|
||||
Default = maps:get(<<"default">>, Value1, <<>>),
|
||||
Form#{Key => Default}
|
||||
end
|
||||
end, #{<<"date4">> => dgiot_datetime:format("YYYY-MM-DD HH:NN")}, FormDesc),
|
||||
end, #{<<"thing1">> => DeviceName, <<"date4">> => dgiot_datetime:format("YYYY-MM-DD HH:NN")}, FormDesc),
|
||||
Par#{<<"thing1">> => FormD};
|
||||
_Oth ->
|
||||
Par
|
||||
|
@ -126,9 +126,9 @@ set_params(Basedata, ProductId) ->
|
||||
<<"setting">> := <<"%s">>} ->
|
||||
case maps:find(Identifier, Basedata) of
|
||||
error ->
|
||||
pass;
|
||||
Acc;
|
||||
{ok, Value} when erlang:byte_size(Value) == 0 ->
|
||||
pass;
|
||||
Acc;
|
||||
{ok, Value} ->
|
||||
FunCode =
|
||||
case OperateType of
|
||||
|
@ -285,6 +285,7 @@ save_pnque(DtuProductId, DtuAddr, ProductId, DevAddr) ->
|
||||
dgiot_data:insert(?DGIOT_PNQUE, DtuId, New_Pn_que)
|
||||
end,
|
||||
Args = dgiot_data:get({?TASK_ARGS, DtuProductId}),
|
||||
?LOG(info, "Args ~p", [Args]),
|
||||
supervisor:start_child(dgiot_task, [Args#{<<"dtuid">> => DtuId}]).
|
||||
|
||||
get_pnque(DtuId) ->
|
||||
|
@ -240,8 +240,9 @@ save_td(#task{app = _App, tid = Channel, product = ProductId, devaddr = DevAddr,
|
||||
Topic = <<"topo/", ProductId/binary, "/", DevAddr/binary, "/post">>,
|
||||
dgiot_mqtt:publish(DevAddr, Topic, Payload),
|
||||
dgiot_tdengine_adapter:save(ProductId, DevAddr, Data),
|
||||
dgiot_mqtt:publish(DevAddr, <<"notification/", ProductId/binary, "/", DevAddr/binary, "/post">>, jsx:encode(Data)),
|
||||
dgiot_bridge:send_log(Channel, "from_dev=> ~ts: ~ts ", [unicode:characters_to_list(Topic), unicode:characters_to_list(jsx:encode(Data))]);
|
||||
NotificationTopic = <<"notification/", ProductId/binary, "/", DevAddr/binary, "/post">>,
|
||||
dgiot_mqtt:publish(DevAddr, NotificationTopic, jsx:encode(Data)),
|
||||
dgiot_bridge:send_log(Channel, "from_Notification=> ~ts: ~ts ", [unicode:characters_to_list(NotificationTopic), unicode:characters_to_list(jsx:encode(Data))]);
|
||||
true ->
|
||||
pass
|
||||
end
|
||||
|
6
apps/dgiot_xinchuangwei/.gitignore
vendored
Normal file
6
apps/dgiot_xinchuangwei/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
.eunit
|
||||
deps
|
||||
*.o
|
||||
*.beam
|
||||
*.plt
|
||||
erl_crash.dump
|
201
apps/dgiot_xinchuangwei/LICENSE
Normal file
201
apps/dgiot_xinchuangwei/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
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.
|
28
apps/dgiot_xinchuangwei/Makefile
Normal file
28
apps/dgiot_xinchuangwei/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
PROJECT = dgiot_acrel
|
||||
PROJECT_DESCRIPTION = dgiot_acrel
|
||||
|
||||
CUR_BRANCH := $(shell git branch | grep -e "^*" | cut -d' ' -f 2)
|
||||
BRANCH := $(if $(filter $(CUR_BRANCH), master develop), $(CUR_BRANCH), develop)
|
||||
|
||||
BUILD_DEPS = emqx cuttlefish ekaf jsx brod supervisor3
|
||||
dep_emqx = git-emqx https://github.com/emqx/emqx $(BRANCH)
|
||||
dep_cuttlefish = git-emqx https://github.com/emqx/cuttlefish v2.2.1
|
||||
|
||||
ERLC_OPTS += +debug_info
|
||||
|
||||
ERLC_OPTS += +'{parse_transform, lager_transform}'
|
||||
|
||||
NO_AUTOPATCH = cuttlefish
|
||||
|
||||
COVER = true
|
||||
|
||||
ERLC_OPTS += +'{parse_transform, lager_transform}'
|
||||
|
||||
$(shell [ -f erlang.mk ] || curl -s -o erlang.mk https://raw.githubusercontent.com/emqx/erlmk/master/erlang.mk)
|
||||
|
||||
include erlang.mk
|
||||
|
||||
app:: rebar.config
|
||||
|
||||
app.config::
|
||||
./deps/cuttlefish/cuttlefish -l info -e etc/ -c etc/dgiot_xinchuangwei.conf -i priv/dgiot_xinchuangwei.schema -d data
|
4
apps/dgiot_xinchuangwei/README.md
Normal file
4
apps/dgiot_xinchuangwei/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
## dgiot_xinchuangwei
|
||||
|
||||
dgiot_xinchuangwei
|
||||
|
1
apps/dgiot_xinchuangwei/erlang.mk
vendored
Normal file
1
apps/dgiot_xinchuangwei/erlang.mk
vendored
Normal file
@ -0,0 +1 @@
|
||||
include ../../erlang.mk
|
0
apps/dgiot_xinchuangwei/etc/dgiot_xinchuangwei.conf
Normal file
0
apps/dgiot_xinchuangwei/etc/dgiot_xinchuangwei.conf
Normal file
43
apps/dgiot_xinchuangwei/include/dgiot_xinchuangwei.hrl
Normal file
43
apps/dgiot_xinchuangwei/include/dgiot_xinchuangwei.hrl
Normal file
@ -0,0 +1,43 @@
|
||||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2016-2017 John liu <34489690@qq.com>.
|
||||
%%
|
||||
%% 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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc dgiot_xinchuangwei COMMAND.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Frame Size Limits
|
||||
%%
|
||||
%% To prevent malicious clients from exploiting memory allocation in a server,
|
||||
%% servers MAY place maximum limits on:
|
||||
%%
|
||||
%% the number of frame headers allowed in a single frame
|
||||
%% the maximum length of header lines
|
||||
%% the maximum size of a frame body
|
||||
%%
|
||||
%% If these limits are exceeded the server SHOULD send the client an ERROR frame
|
||||
%% and then close the connection.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-define(DGIOT_xinchuangwei_DTU, dgiot_xinchuangwei_dtu_ets).
|
||||
-record(state, {
|
||||
id,
|
||||
devaddr = <<>>,
|
||||
dtuproduct,
|
||||
heartcount = 0,
|
||||
app,
|
||||
regtype,
|
||||
env = <<>>
|
||||
}).
|
||||
|
354
apps/dgiot_xinchuangwei/priv/solar_thing.json
Normal file
354
apps/dgiot_xinchuangwei/priv/solar_thing.json
Normal file
@ -0,0 +1,354 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "运行时长",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "17",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "int",
|
||||
"specs": {
|
||||
"max": 9999,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "h",
|
||||
"precision": 0
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "runtime"
|
||||
},
|
||||
{
|
||||
"name": "剩余电量",
|
||||
"dataForm": {
|
||||
"data": "528590",
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "24",
|
||||
"control": "%d",
|
||||
"protocol": "normal",
|
||||
"strategy": "计算值",
|
||||
"byteorder": "big",
|
||||
"collection": "(%%battery_voltage-9)/3.6*100"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "int",
|
||||
"specs": {
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "%"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "dump_energy"
|
||||
},
|
||||
{
|
||||
"name": "累计发电量",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "15",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s*0.1"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"max": 999,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "kW·h",
|
||||
"precision": 3
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "total_power"
|
||||
},
|
||||
{
|
||||
"name": "天发电量",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "13",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 2,
|
||||
"strategy": "20",
|
||||
"byteorder": "big",
|
||||
"collection": "%s*0.01"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"max": 999,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "kW·h"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "day_electricity"
|
||||
},
|
||||
{
|
||||
"name": "充电电流",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "9",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 2,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "int",
|
||||
"specs": {
|
||||
"max": 999,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "mA"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "charge_current"
|
||||
},
|
||||
{
|
||||
"name": "外部温度",
|
||||
"dataForm": {
|
||||
"data": 1,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "12",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 1,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s-40"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "int",
|
||||
"specs": {
|
||||
"max": 999,
|
||||
"min": -100,
|
||||
"step": 0,
|
||||
"unit": "°C"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "outside_temperature"
|
||||
},
|
||||
{
|
||||
"name": "内部温度",
|
||||
"dataForm": {
|
||||
"data": 1,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "11",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 1,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s-40"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "int",
|
||||
"specs": {
|
||||
"max": 999,
|
||||
"min": -100,
|
||||
"step": 0,
|
||||
"unit": "°C"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "core_temperature"
|
||||
},
|
||||
{
|
||||
"name": "太阳能板电压",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "7",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 2,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s*0.1"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"max": 1000,
|
||||
"min": 0,
|
||||
"step": 0.01,
|
||||
"unit": "V"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "v_solarpanel"
|
||||
},
|
||||
{
|
||||
"name": "输出电流",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "5",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 2,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s*0.1"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"max": 1000,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "A"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "i_out"
|
||||
},
|
||||
{
|
||||
"name": "输出电压",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "3",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 2,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s*0.1"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"max": 1000,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "V"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "v_out"
|
||||
},
|
||||
{
|
||||
"name": "电池电压",
|
||||
"dataForm": {
|
||||
"data": 2,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "1",
|
||||
"control": "%d",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 2,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s*0.1"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "float",
|
||||
"specs": {
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"step": 0,
|
||||
"unit": "V"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "battery_voltage"
|
||||
},
|
||||
{
|
||||
"name": "系统状态",
|
||||
"dataForm": {
|
||||
"data": 1,
|
||||
"rate": 1,
|
||||
"order": 1,
|
||||
"round": "all",
|
||||
"offset": 0,
|
||||
"address": "0",
|
||||
"control": "%d",
|
||||
"slaveid": "AA",
|
||||
"protocol": "xinchuangwei",
|
||||
"quantity": 1,
|
||||
"strategy": "2",
|
||||
"byteorder": "big",
|
||||
"collection": "%s",
|
||||
"operatetype": "holdingRegister",
|
||||
"originaltype": "int16"
|
||||
},
|
||||
"dataType": {
|
||||
"type": "enum",
|
||||
"specs": {
|
||||
"0": "正常",
|
||||
"1": "欠压",
|
||||
"2": "负载短路",
|
||||
"3": "负载关路"
|
||||
}
|
||||
},
|
||||
"required": true,
|
||||
"accessMode": "r",
|
||||
"identifier": "system_state"
|
||||
}
|
||||
]
|
||||
}
|
860
apps/dgiot_xinchuangwei/priv/solar_topo.json
Normal file
860
apps/dgiot_xinchuangwei/priv/solar_topo.json
Normal file
@ -0,0 +1,860 @@
|
||||
{
|
||||
"konva": {
|
||||
"Stage": {
|
||||
"attrs": {
|
||||
"x": 310.002476881597,
|
||||
"y": 142.99998881786155,
|
||||
"id": "current1",
|
||||
"width": 1733,
|
||||
"height": 772,
|
||||
"draggable": true
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"attrs": {
|
||||
"listening": false
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"attrs": {},
|
||||
"className": "Image"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": -189.9999999999999,
|
||||
"y": -117.00000000000006,
|
||||
"id": "e494d568c9",
|
||||
"text": "fdasfas",
|
||||
"scaleX": 0.4771162413932782,
|
||||
"scaleY": 0.33855623950755453,
|
||||
"source": ""
|
||||
},
|
||||
"className": "Image"
|
||||
}
|
||||
],
|
||||
"className": "Layer"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"id": "996"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"attrs": {
|
||||
"id": "switch",
|
||||
"width": 2000,
|
||||
"height": 2000
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"attrs": {
|
||||
"x": 310,
|
||||
"y": 144,
|
||||
"id": "dump_energy",
|
||||
"fill": "#000000",
|
||||
"text": "剩余电量",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"container": "",
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 396,
|
||||
"y": 424,
|
||||
"id": "total_power",
|
||||
"fill": "#000000",
|
||||
"text": "累计发电量",
|
||||
"type": "text",
|
||||
"opacity": 0.8,
|
||||
"fontSize": 26,
|
||||
"container": "",
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 43,
|
||||
"y": 424,
|
||||
"id": "day_electricity",
|
||||
"fill": "#000000",
|
||||
"text": "天发电量",
|
||||
"type": "text",
|
||||
"opacity": 0.8,
|
||||
"fontSize": 26,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 138,
|
||||
"y": 348,
|
||||
"id": "charge_current",
|
||||
"fill": "#000000",
|
||||
"text": "充电电流",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 310,
|
||||
"y": 75,
|
||||
"id": "outside_temperature",
|
||||
"fill": "#000000",
|
||||
"text": "外部温度",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 760,
|
||||
"y": 190,
|
||||
"id": "core_temperature",
|
||||
"fill": "#000000",
|
||||
"text": "内部温度",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"container": "",
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 134,
|
||||
"y": 308,
|
||||
"id": "v_solarpanel",
|
||||
"fill": "#000000",
|
||||
"text": "太阳能板电压",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 795,
|
||||
"y": 348,
|
||||
"id": "i_out",
|
||||
"fill": "#000000",
|
||||
"text": "输出电流",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 797,
|
||||
"y": 310,
|
||||
"id": "v_out",
|
||||
"fill": "#000000",
|
||||
"text": "输出电压",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 764,
|
||||
"y": 163,
|
||||
"id": "battery_voltage",
|
||||
"fill": "#000000",
|
||||
"text": "电池电压",
|
||||
"type": "text",
|
||||
"fontSize": 20,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
},
|
||||
{
|
||||
"attrs": {
|
||||
"x": 726,
|
||||
"y": 425,
|
||||
"id": "runtime",
|
||||
"fill": "#000000",
|
||||
"text": "运行时长",
|
||||
"type": "text",
|
||||
"fontSize": 26,
|
||||
"draggable": true,
|
||||
"fontFamily": "Calibri"
|
||||
},
|
||||
"className": "Text"
|
||||
}
|
||||
],
|
||||
"className": "Group"
|
||||
}
|
||||
],
|
||||
"className": "Layer"
|
||||
},
|
||||
{
|
||||
"attrs": {},
|
||||
"children": [],
|
||||
"className": "Layer"
|
||||
}
|
||||
],
|
||||
"className": "Stage"
|
||||
}
|
||||
},
|
||||
"basedate": {
|
||||
"name": "太阳能参数",
|
||||
"cType": "参数",
|
||||
"enable": "1",
|
||||
"params": [
|
||||
{
|
||||
"name": "模式选择",
|
||||
"type": "enum",
|
||||
"unit": "",
|
||||
"bytes": 1,
|
||||
"order": 0,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "0",
|
||||
"attributevalue": "光控+时控"
|
||||
},
|
||||
{
|
||||
"attribute": "1",
|
||||
"attributevalue": "感应"
|
||||
},
|
||||
{
|
||||
"attribute": "2",
|
||||
"attributevalue": "调试"
|
||||
},
|
||||
{
|
||||
"attribute": "3",
|
||||
"attributevalue": "纯光控"
|
||||
},
|
||||
{
|
||||
"attribute": "4",
|
||||
"attributevalue": "手动模式"
|
||||
},
|
||||
{
|
||||
"attribute": "5",
|
||||
"attributevalue": "常开模式"
|
||||
}
|
||||
],
|
||||
"isshow": true,
|
||||
"struct": {
|
||||
"0": "光控+时控",
|
||||
"1": "感应",
|
||||
"2": "调试",
|
||||
"3": "纯光控",
|
||||
"4": "手动模式",
|
||||
"5": "常开模式"
|
||||
},
|
||||
"address": "0",
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": false,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "mode_selection"
|
||||
},
|
||||
{
|
||||
"name": "电池类型",
|
||||
"type": "enum",
|
||||
"unit": "",
|
||||
"bytes": 1,
|
||||
"order": 1,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "0",
|
||||
"attributevalue": "锂3.2"
|
||||
},
|
||||
{
|
||||
"attribute": "1",
|
||||
"attributevalue": "锂6.4"
|
||||
},
|
||||
{
|
||||
"attribute": "2",
|
||||
"attributevalue": "锂12.8"
|
||||
},
|
||||
{
|
||||
"attribute": "3",
|
||||
"attributevalue": "铅酸12"
|
||||
}
|
||||
],
|
||||
"isshow": true,
|
||||
"struct": {
|
||||
"0": "锂3.2",
|
||||
"1": "锂6.4",
|
||||
"2": "锂12.8",
|
||||
"3": "铅酸12"
|
||||
},
|
||||
"address": "1",
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "battery_type"
|
||||
},
|
||||
{
|
||||
"name": "过充电压",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 2,
|
||||
"order": 2,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": true,
|
||||
"struct": {},
|
||||
"address": "2",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "v_over"
|
||||
},
|
||||
{
|
||||
"name": "欠压保护",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 2,
|
||||
"order": 3,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "4",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "low_voltage"
|
||||
},
|
||||
{
|
||||
"name": "恢复电压",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 2,
|
||||
"order": 4,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "6",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "urec"
|
||||
},
|
||||
{
|
||||
"name": "开灯电压",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 1,
|
||||
"order": 5,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "8",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "onlight_voltage"
|
||||
},
|
||||
{
|
||||
"name": "关灯电压",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 1,
|
||||
"order": 6,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "9",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "offlights_voltage"
|
||||
},
|
||||
{
|
||||
"name": "开灯延时",
|
||||
"type": "int",
|
||||
"unit": "s",
|
||||
"bytes": 1,
|
||||
"order": 7,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "10",
|
||||
"default": 1,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "onlight_delay"
|
||||
},
|
||||
{
|
||||
"name": "是否打开智能管理",
|
||||
"type": "enum",
|
||||
"unit": "",
|
||||
"bytes": 1,
|
||||
"order": 8,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "0",
|
||||
"attributevalue": "否"
|
||||
},
|
||||
{
|
||||
"attribute": "1",
|
||||
"attributevalue": "是"
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "11",
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "is_tzims"
|
||||
},
|
||||
{
|
||||
"name": "第一区间电压",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 2,
|
||||
"order": 9,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "12",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "first_interval_voltage"
|
||||
},
|
||||
{
|
||||
"name": "第二区间电压",
|
||||
"type": "float",
|
||||
"unit": "V",
|
||||
"bytes": 2,
|
||||
"order": 10,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "14",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "second_interval_voltage"
|
||||
},
|
||||
{
|
||||
"name": "第一时段时长",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 11,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "16",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "first_duration"
|
||||
},
|
||||
{
|
||||
"name": "第一时段功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 12,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "17",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "first_period_power"
|
||||
},
|
||||
{
|
||||
"name": "第二时段时长",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 13,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "18",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "second_duration"
|
||||
},
|
||||
{
|
||||
"name": "第二时段功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 14,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "19",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "second_period_power"
|
||||
},
|
||||
{
|
||||
"name": "第三时段时长",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 15,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "20",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "third_duration"
|
||||
},
|
||||
{
|
||||
"name": "第三时段功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 16,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "21",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "third_period_power"
|
||||
},
|
||||
{
|
||||
"name": "第四时段时长",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 17,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "22",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "fourth_duration"
|
||||
},
|
||||
{
|
||||
"name": "第四时段功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 18,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "23",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "fourth_period_power"
|
||||
},
|
||||
{
|
||||
"name": "晨亮时段时长",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 19,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "24",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "morning_duration "
|
||||
},
|
||||
{
|
||||
"name": "晨亮时段功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 20,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "25",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "morning_period_power"
|
||||
},
|
||||
{
|
||||
"name": "红外时段时长",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 21,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "26",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "infrared_time_duration"
|
||||
},
|
||||
{
|
||||
"name": "有人功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 22,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "27",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "effective_input_power"
|
||||
},
|
||||
{
|
||||
"name": "无人功率",
|
||||
"type": "int",
|
||||
"unit": "%",
|
||||
"bytes": 1,
|
||||
"order": 23,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "28",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "there_is_no_power"
|
||||
},
|
||||
{
|
||||
"name": "感应延时",
|
||||
"type": "float",
|
||||
"unit": "h",
|
||||
"bytes": 1,
|
||||
"order": 24,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "29",
|
||||
"setting": "%s*10",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s*0.1",
|
||||
"identifier": "induction_time_delay"
|
||||
},
|
||||
{
|
||||
"name": "最大输出电流",
|
||||
"type": "int",
|
||||
"unit": "mA",
|
||||
"bytes": 2,
|
||||
"order": 25,
|
||||
"specs": [
|
||||
{
|
||||
"attribute": "",
|
||||
"attributevalue": ""
|
||||
}
|
||||
],
|
||||
"isshow": false,
|
||||
"struct": {},
|
||||
"address": "32",
|
||||
"default": 0,
|
||||
"setting": "%s",
|
||||
"protocol": "xinchuangwei",
|
||||
"readonly": true,
|
||||
"required": false,
|
||||
"collection": "%s",
|
||||
"identifier": "max_current_output"
|
||||
}
|
||||
],
|
||||
"description": "1"
|
||||
}
|
||||
}
|
11
apps/dgiot_xinchuangwei/priv/swagger/dgiot_xinchuangwei.json
Normal file
11
apps/dgiot_xinchuangwei/priv/swagger/dgiot_xinchuangwei.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"tags": [
|
||||
{
|
||||
"name": "xinchuangwei",
|
||||
"description": "新创微"
|
||||
}
|
||||
],
|
||||
"definitions": {},
|
||||
"paths": {
|
||||
}
|
||||
}
|
3
apps/dgiot_xinchuangwei/rebar.config
Normal file
3
apps/dgiot_xinchuangwei/rebar.config
Normal file
@ -0,0 +1,3 @@
|
||||
{deps, [
|
||||
|
||||
]}.
|
7
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei.app.src
Normal file
7
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei.app.src
Normal file
@ -0,0 +1,7 @@
|
||||
{application,dgiot_xinchuangwei,
|
||||
[{description,"DGIOT xinchuangwei"},
|
||||
{vsn,"4.3.0"},
|
||||
{modules,[]},
|
||||
{registered,[dgiot_xinchuangwei_sup]},
|
||||
{applications,[kernel,stdlib,dgiot]},
|
||||
{mod,{dgiot_xinchuangwei_app,[]}}]}.
|
@ -0,0 +1,25 @@
|
||||
%%-*- mode: erlang -*-
|
||||
%% .app.src.script
|
||||
|
||||
RemoveLeadingV =
|
||||
fun(Tag) ->
|
||||
case re:run(Tag, "v\[0-9\]+\.\[0-9\]+\.*") of
|
||||
nomatch ->
|
||||
Tag;
|
||||
{match, _} ->
|
||||
%% if it is a version number prefixed by 'v' then remove the 'v'
|
||||
"v" ++ Vsn = Tag,
|
||||
Vsn
|
||||
end
|
||||
end,
|
||||
|
||||
case os:getenv("EMQX_DEPS_DEFAULT_VSN") of
|
||||
false -> CONFIG; % env var not defined
|
||||
[] -> CONFIG; % env var set to empty string
|
||||
Tag ->
|
||||
[begin
|
||||
AppConf0 = lists:keystore(vsn, 1, AppConf, {vsn, RemoveLeadingV(Tag)}),
|
||||
{application, App, AppConf0}
|
||||
end || Conf = {application, App, AppConf} <- CONFIG]
|
||||
end.
|
||||
|
77
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei.erl
Normal file
77
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei.erl
Normal file
@ -0,0 +1,77 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author stoneliu
|
||||
%%% @copyright (C) 2020, <COMPANY>
|
||||
%%% @doc
|
||||
%%% solarPower
|
||||
%%% @end
|
||||
%%% Created : 07. 五月 2021 12:00
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(dgiot_xinchuangwei).
|
||||
-author("stoneliu").
|
||||
-export([create_product/1, create_device/4, test/1]).
|
||||
-include_lib("dgiot/include/logger.hrl").
|
||||
|
||||
%% 16#c3
|
||||
%% Buff = <<16#AA, 16#12, 16#00, 16#03, 16#02, 16#02, 16#, 16#01>>.
|
||||
%% dgiot_xinchuangwei:test(Buff).
|
||||
test(Buff) ->
|
||||
CheckCrc = dgiot_xinchuangwei_decoder:crc16(Buff),
|
||||
Payload = <<Buff/binary, CheckCrc:8>>,
|
||||
dgiot_xinchuangwei_decoder:parse_frame(Payload, #{<<"dtuproduct">> => <<"3a8490e534">>, <<"devaddr">> => <<"xinchuangweitest">>}).
|
||||
|
||||
create_product(#{
|
||||
<<"DTUTYPE">> := DTUTYPE,
|
||||
<<"ACL">> := Acl,
|
||||
<<"productname">> := Productname}) ->
|
||||
Thing = dgiot_license:load_config(?MODULE, "solar_thing"),
|
||||
Topo = dgiot_license:load_config(?MODULE, "solar_topo"),
|
||||
case dgiot_parse:query_object(<<"Product">>, #{<<"where">> => #{<<"name">> => Productname}}) of
|
||||
{ok, #{<<"results">> := [#{<<"objectId">> := ObjectId} | _]}} ->
|
||||
{ok, #{<<"objectId">> => ObjectId}};
|
||||
_ ->
|
||||
R = dgiot_parse:create_object(<<"Product">>, #{<<"name">> => Productname,
|
||||
<<"devType">> => <<"dgiot_", DTUTYPE/binary, "_dtu">>,
|
||||
<<"desc">> => Productname,
|
||||
<<"netType">> => <<"4G">>,
|
||||
<<"category">> => <<"IotHub">>,
|
||||
<<"config">> => Topo,
|
||||
<<"thing">> => Thing,
|
||||
<<"nodeType">> => 1,
|
||||
<<"ACL">> => Acl,
|
||||
<<"productSecret">> => license_loader:random(),
|
||||
<<"dynamicReg">> => true}),
|
||||
R
|
||||
end.
|
||||
|
||||
create_device(DeviceId, ProductId, DTUMAC, DTUIP) ->
|
||||
case dgiot_parse:get_object(<<"Product">>, ProductId) of
|
||||
{ok, #{<<"ACL">> := Acl, <<"devType">> := DevType, <<"name">> := ProductName}} ->
|
||||
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">> => <<ProductName/binary, DTUMAC/binary>>,
|
||||
<<"ip">> => DTUIP,
|
||||
<<"isEnable">> => true,
|
||||
<<"product">> => ProductId,
|
||||
<<"ACL">> => Acl,
|
||||
<<"status">> => <<"ONLINE">>,
|
||||
<<"location">> => #{<<"__type">> => <<"GeoPoint">>, <<"longitude">> => 120.161324, <<"latitude">> => 30.262441},
|
||||
<<"brand">> => <<ProductName/binary>>,
|
||||
<<"devModel">> => DevType,
|
||||
<<"basedata">> => #{}
|
||||
}),
|
||||
dgiot_task:save_pnque(ProductId, DTUMAC, ProductId, DTUMAC)
|
||||
end;
|
||||
Error2 -> ?LOG(info, "Error2 ~p ", [Error2])
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
37
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_app.erl
Normal file
37
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_app.erl
Normal file
@ -0,0 +1,37 @@
|
||||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2016-2017 John liu <34489690@qq.com>.
|
||||
%%
|
||||
%% 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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc dgiot_xinchuangwei Application
|
||||
-module(dgiot_xinchuangwei_app).
|
||||
-include("dgiot_xinchuangwei.hrl").
|
||||
-behaviour(application).
|
||||
-emqx_plugin(?MODULE).
|
||||
|
||||
%% Application callbacks
|
||||
-export([start/2, stop/1]).
|
||||
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Application callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
start(_StartType, _StartArgs) ->
|
||||
dgiot_data:init(?DGIOT_xinchuangwei_DTU),
|
||||
dgiot_xinchuangwei_sup:start_link().
|
||||
|
||||
|
||||
stop(_State) ->
|
||||
ok.
|
198
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_channel.erl
Normal file
198
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_channel.erl
Normal file
@ -0,0 +1,198 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2019, <COMPANY>
|
||||
%%% @doc
|
||||
%%% 前置机客户端
|
||||
%%% @end
|
||||
%%% Created : 07. 五月 2021 12:00
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(dgiot_xinchuangwei_channel).
|
||||
-behavior(dgiot_channelx).
|
||||
-author("johnliu").
|
||||
-define(TYPE, <<"XINCHUANGWEI">>).
|
||||
-define(MAX_BUFF_SIZE, 1024).
|
||||
-include("dgiot_xinchuangwei.hrl").
|
||||
-include_lib("dgiot/include/logger.hrl").
|
||||
|
||||
%% API
|
||||
-export([start/2]).
|
||||
|
||||
%% Channel callback
|
||||
-export([init/3, handle_init/1, handle_event/3, handle_message/2, stop/3]).
|
||||
|
||||
|
||||
%% 注册通道类型
|
||||
-channel(?TYPE).
|
||||
-channel_type(#{
|
||||
type => 1,
|
||||
title => #{
|
||||
zh => <<"新创微控制器采集通道"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
zh => <<"新创微控制器采集通道"/utf8>>
|
||||
}
|
||||
}).
|
||||
%% 注册通道参数
|
||||
-params(#{
|
||||
<<"port">> => #{
|
||||
order => 1,
|
||||
type => integer,
|
||||
required => true,
|
||||
default => 20110,
|
||||
title => #{
|
||||
zh => <<"端口"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
zh => <<"侦听端口"/utf8>>
|
||||
}
|
||||
},
|
||||
<<"regtype">> => #{
|
||||
order => 2,
|
||||
type => string,
|
||||
required => true,
|
||||
default => <<"上传IMEI"/utf8>>,
|
||||
title => #{
|
||||
zh => <<"注册类型"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
zh => <<"上传IMEI"/utf8>>
|
||||
}
|
||||
},
|
||||
<<"dtutype">> => #{
|
||||
order => 3,
|
||||
type => string,
|
||||
required => true,
|
||||
default => <<"TAS">>,
|
||||
title => #{
|
||||
zh => <<"控制器厂商"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
zh => <<"控制器厂商"/utf8>>
|
||||
}
|
||||
},
|
||||
<<"heartbeat">> => #{
|
||||
order => 4,
|
||||
type => integer,
|
||||
required => true,
|
||||
default => 10,
|
||||
title => #{
|
||||
zh => <<"心跳周期"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
zh => <<"心跳周期"/utf8>>
|
||||
}
|
||||
},
|
||||
<<"productname">> => #{
|
||||
order => 5,
|
||||
type => string,
|
||||
required => true,
|
||||
default => <<"新创微控制器"/utf8>>,
|
||||
title => #{
|
||||
zh => <<"产品名称"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
zh => <<"产品名称,用于创建产品"/utf8>>
|
||||
}
|
||||
},
|
||||
<<"ico">> => #{
|
||||
order => 102,
|
||||
type => string,
|
||||
required => false,
|
||||
default => <<"http://dgiot-1253666439.cos.ap-shanghai-fsi.myqcloud.com/shuwa_tech/zh/product/dgiot/channel/xinchuangweilog.png">>,
|
||||
title => #{
|
||||
en => <<"channel ICO">>,
|
||||
zh => <<"通道ICO"/utf8>>
|
||||
},
|
||||
description => #{
|
||||
en => <<"channel ICO">>,
|
||||
zh => <<"通道ICO"/utf8>>
|
||||
}
|
||||
}
|
||||
}).
|
||||
|
||||
|
||||
start(ChannelId, ChannelArgs) ->
|
||||
dgiot_channelx:add(?TYPE, ChannelId, ?MODULE, ChannelArgs).
|
||||
|
||||
%% 通道初始化
|
||||
init(?TYPE, ChannelId, #{
|
||||
<<"port">> := Port,
|
||||
<<"heartbeat">> := Heartbeat,
|
||||
<<"regtype">> := Type,
|
||||
<<"product">> := Products,
|
||||
<<"dtutype">> := DTUTYPE,
|
||||
<<"productname">> := Productname
|
||||
} = Args) ->
|
||||
_Env = get_newenv(Args),
|
||||
[{App, DtuProductId} | _] = get_app(Products, DTUTYPE, Productname),
|
||||
State = #state{
|
||||
id = ChannelId,
|
||||
regtype = Type,
|
||||
app = App,
|
||||
dtuproduct = DtuProductId
|
||||
},
|
||||
dgiot_data:insert({ChannelId, heartbeat}, Heartbeat),
|
||||
{ok, State, dgiot_xinchuangwei_tcp:start(Port, State)};
|
||||
|
||||
init(?TYPE, _ChannelId, _Args) ->
|
||||
{ok, #{}, #{}}.
|
||||
|
||||
%% 当前通道
|
||||
handle_init(State) ->
|
||||
dgiot_parse:subscribe(<<"Device/*">>, put),
|
||||
dgiot_parse:subscribe(<<"Product">>, post),
|
||||
{ok, State}.
|
||||
%% 通道消息处理,注意:进程池调用
|
||||
handle_event(_EventId, Event, State) ->
|
||||
?LOG(info, "Channel ~p", [Event]),
|
||||
{ok, State}.
|
||||
|
||||
handle_message({sync_parse, Args}, State) ->
|
||||
case jsx:decode(Args, [return_maps]) of
|
||||
#{<<"basedata">> := Basedata, <<"devaddr">> := Devaddr, <<"product">> := #{<<"objectId">> := ProductId}} ->
|
||||
%% 设置参数
|
||||
Payloads = dgiot_xinchuangwei_decoder:set_params(Basedata, ProductId),
|
||||
Modbuspayloads = modbus_rtu:set_params(Basedata, ProductId),
|
||||
Topic = <<"setXinchuangwei/", ProductId/binary, "/", Devaddr/binary>>,
|
||||
dgiot_mqtt:publish(self(), Topic, lists:append(Payloads, Modbuspayloads));
|
||||
#{<<"name">> := _Name, <<"productSecret">> := _ProductSecret, <<"objectId">> := _ObjectId, <<"ACL">> := _ACL} ->
|
||||
pass;
|
||||
_ ->
|
||||
pass
|
||||
end,
|
||||
{ok, State};
|
||||
|
||||
handle_message(Message, State) ->
|
||||
?LOG(info, "Channel ~p", [Message]),
|
||||
{ok, State}.
|
||||
|
||||
stop(ChannelType, ChannelId, _State) ->
|
||||
?LOG(warning, "Channel[~p,~p] stop", [ChannelType, ChannelId]),
|
||||
ok.
|
||||
|
||||
get_app(Products, DTUTYPE, Productname) ->
|
||||
lists:map(fun({_ProductId, #{<<"ACL">> := Acl}}) ->
|
||||
Predicate = fun(E) ->
|
||||
case E of
|
||||
<<"role:", _/binary>> -> true;
|
||||
_ -> false
|
||||
end
|
||||
end,
|
||||
DtuProductId =
|
||||
case dgiot_xinchuangwei:create_product(#{<<"DTUTYPE">> => dgiot_utils:to_binary(DTUTYPE), <<"ACL">> => Acl, <<"productname">> => Productname}) of
|
||||
{_, #{<<"objectId">> := DtuProductId1}} ->
|
||||
%% dgiot_product:load(DtuProductId1),
|
||||
DtuProductId1;
|
||||
_ -> <<"">>
|
||||
end,
|
||||
dgiot_product:load(DtuProductId),
|
||||
[<<"role:", App/binary>> | _] = lists:filter(Predicate, maps:keys(Acl)),
|
||||
{App, DtuProductId}
|
||||
end, Products).
|
||||
|
||||
get_newenv(Args) ->
|
||||
maps:without([
|
||||
<<"behaviour">>,
|
||||
<<"MaxOverFlow">>,
|
||||
<<"Size">>,
|
||||
<<"applicationtText">>,
|
||||
<<"product">>], Args).
|
44
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_sup.erl
Normal file
44
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_sup.erl
Normal file
@ -0,0 +1,44 @@
|
||||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2016-2017 John liu <34489690@qq.com>.
|
||||
%%
|
||||
%% 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.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% @doc dgiot_xinchuangwei supervisor
|
||||
-module(dgiot_xinchuangwei_sup).
|
||||
-include("dgiot_xinchuangwei.hrl").
|
||||
-behaviour(supervisor).
|
||||
|
||||
%% API
|
||||
-export([start_link/0]).
|
||||
|
||||
%% Supervisor callbacks
|
||||
-export([init/1]).
|
||||
|
||||
%% Helper macro for declaring children of supervisor
|
||||
-define(CHILD(I, Type), {I, {I, start_link, []}, permanent, 5000, Type, [I]}).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% API functions
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
start_link() ->
|
||||
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Supervisor callbacks
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
init([]) ->
|
||||
{ok, { {one_for_one, 5, 10}, []}}.
|
||||
|
236
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_tcp.erl
Normal file
236
apps/dgiot_xinchuangwei/src/dgiot_xinchuangwei_tcp.erl
Normal file
@ -0,0 +1,236 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author liuxiaodong
|
||||
%%% @copyright (C) 2021, <COMPANY>
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 04. 6月 2021 11:02
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(dgiot_xinchuangwei_tcp).
|
||||
-author("liuxiaodong").
|
||||
-include_lib("dgiot/include/dgiot_socket.hrl").
|
||||
-include("dgiot_xinchuangwei.hrl").
|
||||
-include_lib("dgiot/include/logger.hrl").
|
||||
|
||||
%% API
|
||||
-export([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).
|
||||
|
||||
%% =======================
|
||||
%% tcp server start
|
||||
%% {ok, State} | {stop, Reason}
|
||||
init(#tcp{state = #state{id = ChannelId}} = TCPState) ->
|
||||
case dgiot_bridge:get_products(ChannelId) of
|
||||
{ok, _, _ProductIds} ->
|
||||
{ok, TCPState};
|
||||
{error, not_find} ->
|
||||
{stop, not_find_channel}
|
||||
end.
|
||||
|
||||
%% dtu 登录报文
|
||||
handle_info({tcp, Buff}, #tcp{socket = Socket, state = #state{id = ChannelId, devaddr = <<>>, dtuproduct = ProductId} = State} = TCPState) when byte_size(Buff) == 15 ->
|
||||
dgiot_bridge:send_log(ChannelId, "DTU revice from ~p", [dgiot_utils:binary_to_hex(Buff)]),
|
||||
DTUIP = dgiot_utils:get_ip(Socket),
|
||||
DtuAddr = Buff,
|
||||
#{<<"objectId">> := DeviceId} =
|
||||
dgiot_parse:get_objectid(<<"Device">>, #{<<"product">> => ProductId, <<"devaddr">> => DtuAddr}),
|
||||
dgiot_xinchuangwei:create_device(DeviceId, ProductId, DtuAddr, DTUIP),
|
||||
Topic = <<"setXinchuangwei/", ProductId/binary, "/", DtuAddr/binary>>,
|
||||
dgiot_mqtt:subscribe(Topic),
|
||||
erlang:send_after(18 * 1000, self(), readparams),
|
||||
%% erlang:send_after(10 * 1000, self(), readstatus),
|
||||
{noreply, TCPState#tcp{buff = <<>>, state = State#state{devaddr = DtuAddr}}};
|
||||
|
||||
%% 接收 dtu 返回报文
|
||||
handle_info({tcp, Buff}, #tcp{state = #state{id = ChannelId, devaddr = DevAddr, dtuproduct = DtuProductId, env = Env} = State} = TCPState) ->
|
||||
dgiot_bridge:send_log(ChannelId, "xinchuangwei revice from ~p", [dgiot_utils:binary_to_hex(Buff)]),
|
||||
case dgiot_xinchuangwei_decoder:parse_frame(Buff, State) of
|
||||
{status, Ack} ->
|
||||
?LOG(info, "Ack ~p", [Ack]),
|
||||
NewTopic = <<"thing/", DtuProductId/binary, "/", DevAddr/binary, "/post">>,
|
||||
dgiot_bridge:send_log(ChannelId, "to_task: ~p: ~p ~n", [NewTopic, jsx:encode(Ack)]),
|
||||
dgiot_mqtt:publish(DevAddr, NewTopic, jsx:encode(Ack));
|
||||
{error, _} ->
|
||||
#{product := ProductId, pn := Pn, di := Di} = Env,
|
||||
<<H:8, L:8>> = dgiot_utils:hex_to_binary(modbus_rtu:is16(Di)),
|
||||
<<Sh:8, Sl:8>> = dgiot_utils:hex_to_binary(modbus_rtu:is16(Pn)),
|
||||
case modbus_rtu:parse_frame(Buff, [], #{
|
||||
<<"dtuproduct">> => ProductId,
|
||||
<<"channel">> => ChannelId,
|
||||
<<"dtuaddr">> => DevAddr,
|
||||
<<"slaveId">> => Sh * 256 + Sl,
|
||||
<<"address">> => H * 256 + L}) of
|
||||
{_, Things} ->
|
||||
?LOG(info, "Things ~p", [Things]),
|
||||
NewTopic = <<"thing/", DtuProductId/binary, "/", DevAddr/binary, "/post">>,
|
||||
dgiot_bridge:send_log(ChannelId, "end to_task: ~p: ~p ~n", [NewTopic, jsx:encode(Things)]),
|
||||
dgiot_mqtt:publish(DevAddr, NewTopic, jsx:encode(Things));
|
||||
Other ->
|
||||
?LOG(info, "Other ~p", [Other]),
|
||||
pass
|
||||
end;
|
||||
_ ->
|
||||
pass
|
||||
end,
|
||||
{noreply, TCPState};
|
||||
|
||||
handle_info(login, #tcp{state = #state{id = ChannelId, dtuproduct = ProductId}} = TCPState) ->
|
||||
dgiot_bridge:send_log(ChannelId, "ChannelId ~p ProductId ~p", [ChannelId, ProductId]),
|
||||
{noreply, TCPState#tcp{buff = <<>>}};
|
||||
|
||||
%% 一次读取所有状态
|
||||
%% 55 03 00 13 6B
|
||||
handle_info(readstatus, #tcp{state = #state{id = ChannelId}} = TCPState) ->
|
||||
Heartbeat =
|
||||
case dgiot_data:get({ChannelId, heartbeat}) of
|
||||
not_find ->
|
||||
<<"5">>;
|
||||
Heartbeat1 ->
|
||||
Heartbeat1
|
||||
end,
|
||||
Payload = <<16#55, 16#03, 16#00, 16#13, 16#6B>>,
|
||||
dgiot_tcp_server:send(TCPState, Payload),
|
||||
dgiot_bridge:send_log(ChannelId, "readstatus to_dtu ~p", [dgiot_utils:binary_to_hex(Payload)]),
|
||||
erlang:send_after(Heartbeat * 1000, self(), readstatus),
|
||||
{noreply, TCPState};
|
||||
|
||||
%% 一次读取所有参数
|
||||
%% 55 02 00 29 80
|
||||
handle_info(readparams, #tcp{state = #state{id = ChannelId}} = TCPState) ->
|
||||
Payload = <<16#55, 16#02, 16#00, 16#29, 16#80>>,
|
||||
dgiot_tcp_server:send(TCPState, Payload),
|
||||
dgiot_bridge:send_log(ChannelId, "readparams to_dtu ~p", [dgiot_utils:binary_to_hex(Payload)]),
|
||||
{noreply, TCPState};
|
||||
|
||||
%% 设置参数
|
||||
handle_info({deliver, _Topic, Msg}, #tcp{state = #state{id = ChannelId} = State} = TCPState) ->
|
||||
Payload = dgiot_mqtt:get_payload(Msg),
|
||||
case jsx:is_json(Payload) of
|
||||
true ->
|
||||
case binary:split(dgiot_mqtt:get_topic(Msg), <<$/>>, [global, trim]) of
|
||||
[<<"setXinchuangwei">>, _ProductId, _DtuAddr] ->
|
||||
%% 设置参数
|
||||
lists:map(fun(X) ->
|
||||
dgiot_tcp_server:send(TCPState, X),
|
||||
timer:sleep(1500)
|
||||
end, Payload),
|
||||
erlang:send_after(1000, self(), readparams),
|
||||
{noreply, TCPState};
|
||||
[<<"profile">>, ProductId, _DtuAddr] ->
|
||||
case Payload of
|
||||
#{<<"_dgiotprotocol">> := <<"xinchuangwei">>} ->
|
||||
Payloads = dgiot_xinchuangwei_decoder:set_params(maps:without([<<"_dgiotprotocol">>], Payload), ProductId),
|
||||
lists:map(fun(X) ->
|
||||
dgiot_tcp_server:send(TCPState, X)
|
||||
end, Payloads),
|
||||
erlang:send_after(1000, self(), readparams);
|
||||
_ ->
|
||||
pass
|
||||
end,
|
||||
{noreply, TCPState};
|
||||
[<<"thing">>, _DtuProductId, _DtuAddr] ->
|
||||
[#{<<"thingdata">> := ThingData} | _] = jsx:decode(dgiot_mqtt:get_payload(Msg), [{labels, binary}, return_maps]),
|
||||
%% ?LOG(error, "ThingData ~p", [ThingData]),
|
||||
case ThingData of
|
||||
#{<<"command">> := <<"r">>,
|
||||
<<"data">> := Value,
|
||||
<<"di">> := Di,
|
||||
<<"pn">> := SlaveId,
|
||||
<<"product">> := ProductId,
|
||||
<<"protocol">> := <<"modbus">>
|
||||
} ->
|
||||
Datas = modbus_rtu:to_frame(#{
|
||||
<<"addr">> => SlaveId,
|
||||
<<"value">> => Value,
|
||||
<<"productid">> => ProductId,
|
||||
<<"di">> => Di}),
|
||||
lists:map(fun(X) ->
|
||||
dgiot_bridge:send_log(ChannelId, "to_device: ~p ", [dgiot_utils:binary_to_hex(X)]),
|
||||
dgiot_tcp_server:send(TCPState, X)
|
||||
end, Datas),
|
||||
{noreply, TCPState#tcp{state = State#state{env = #{product => ProductId, pn => SlaveId, di => Di}}}};
|
||||
#{<<"command">> := <<"rw">>,
|
||||
<<"data">> := Value,
|
||||
<<"di">> := Di,
|
||||
<<"pn">> := SlaveId,
|
||||
<<"product">> := ProductId,
|
||||
<<"protocol">> := <<"modbus">>
|
||||
} ->
|
||||
Datas = modbus_rtu:to_frame(#{
|
||||
<<"addr">> => SlaveId,
|
||||
<<"value">> => Value,
|
||||
<<"productid">> => ProductId,
|
||||
<<"di">> => Di}),
|
||||
lists:map(fun(X) ->
|
||||
dgiot_bridge:send_log(ChannelId, "to_device: ~p ", [dgiot_utils:binary_to_hex(X)]),
|
||||
dgiot_tcp_server:send(TCPState, X)
|
||||
end, Datas),
|
||||
{noreply, TCPState#tcp{state = State#state{env = #{product => ProductId, pn => SlaveId, di => Di}}}};
|
||||
_Ot ->
|
||||
%% task采集指令 状态
|
||||
StatusPayload = <<16#55, 16#03, 16#00, 16#13, 16#6B>>,
|
||||
dgiot_tcp_server:send(TCPState, StatusPayload),
|
||||
dgiot_bridge:send_log(ChannelId, "readstatus to_dtu ~p", [dgiot_utils:binary_to_hex(StatusPayload)]),
|
||||
{noreply, TCPState}
|
||||
end;
|
||||
_Other ->
|
||||
?LOG(info, "_Other ~p ", [_Other]),
|
||||
{noreply, TCPState}
|
||||
end;
|
||||
false ->
|
||||
case binary:split(dgiot_mqtt:get_topic(Msg), <<$/>>, [global, trim]) of
|
||||
[<<"setXinchuangwei">>, _ProductId, _DtuAddr] ->
|
||||
%% 设置参数
|
||||
lists:map(fun(X) ->
|
||||
dgiot_tcp_server:send(TCPState, X),
|
||||
timer:sleep(1000)
|
||||
end, Payload),
|
||||
erlang:send_after(1000, self(), readparams),
|
||||
{noreply, TCPState};
|
||||
[<<"profile">>, ProductId, _DtuAddr] ->
|
||||
%% 设置参数
|
||||
case Payload of
|
||||
#{<<"_dgiotprotocol">> := <<"xinchuangwei">>} ->
|
||||
Payloads = dgiot_xinchuangwei_decoder:set_params(maps:without([<<"_dgiotprotocol">>], Payload), ProductId),
|
||||
lists:map(fun(X) ->
|
||||
dgiot_tcp_server:send(TCPState, X)
|
||||
end, Payloads),
|
||||
erlang:send_after(1000, self(), readparams);
|
||||
_ ->
|
||||
pass
|
||||
end,
|
||||
{noreply, TCPState};
|
||||
_ ->
|
||||
{noreply, TCPState}
|
||||
end
|
||||
end;
|
||||
|
||||
%% {stop, TCPState} | {stop, Reason} | {ok, TCPState} | ok | stop
|
||||
handle_info(_Info, TCPState) ->
|
||||
{noreply, TCPState}.
|
||||
|
||||
handle_call(_Msg, _From, TCPState) ->
|
||||
{reply, ok, TCPState}.
|
||||
|
||||
handle_cast(_Msg, TCPState) ->
|
||||
{noreply, TCPState}.
|
||||
|
||||
terminate(_Reason, #tcp{state = #state{devaddr = _DevAddr, dtuproduct = _ProductId}} = _TCPState) ->
|
||||
%% case DevAddr =/= <<>> of
|
||||
%% true ->
|
||||
%% #{<<"objectId">> := DeviceId} = dgiot_parse:get_objectid(<<"Device">>, #{<<"product">> => ProductId, <<"devaddr">> => DevAddr}),
|
||||
%% dgiot_parse:update_object(<<"Device">>, DeviceId, #{<<"status">> => <<"OFFLINE">>});
|
||||
%% false ->
|
||||
%% pass
|
||||
%% end,
|
||||
ok.
|
||||
|
||||
code_change(_OldVsn, TCPState, _Extra) ->
|
||||
{ok, TCPState}.
|
||||
|
||||
|
@ -0,0 +1,78 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author stoneliu
|
||||
%%% @copyright (C) 2019, dgiot
|
||||
%%% @doc
|
||||
%%% API 处理模块
|
||||
%%% Created : 07. 五月 2021 12:00
|
||||
%%% @end
|
||||
%%%-------------------------------------------------------------------
|
||||
-module(dgiot_xinchuangwei_handler).
|
||||
-author("stoneliu").
|
||||
-behavior(dgiot_rest).
|
||||
-dgiot_rest(all).
|
||||
-include_lib("dgiot/include/logger.hrl").
|
||||
|
||||
%% API
|
||||
-export([swagger_xinchuangwei/0]).
|
||||
-export([handle/4]).
|
||||
|
||||
%% API描述
|
||||
%% 支持二种方式导入
|
||||
%% 示例:
|
||||
%% 1. Metadata为map表示的JSON,
|
||||
%% dgiot_http_server:bind(<<"/pump">>, ?MODULE, [], Metadata)
|
||||
%% 2. 从模块的priv/swagger/下导入
|
||||
%% dgiot_http_server:bind(<<"/swagger_feeders.json">>, ?MODULE, [], priv)
|
||||
swagger_xinchuangwei() ->
|
||||
[
|
||||
dgiot_http_server:bind(<<"/swagger_xinchuangwei.json">>, ?MODULE, [], priv)
|
||||
].
|
||||
|
||||
|
||||
%%%===================================================================
|
||||
%%% 请求处理
|
||||
%%% 如果登录, Context 内有 <<"user">>, version
|
||||
%%%===================================================================
|
||||
|
||||
-spec handle(OperationID :: atom(), Args :: map(), Context :: map(), Req :: dgiot_req:req()) ->
|
||||
{Status :: dgiot_req:http_status(), Body :: map()} |
|
||||
{Status :: dgiot_req:http_status(), Headers :: map(), Body :: map()} |
|
||||
{Status :: dgiot_req:http_status(), Headers :: map(), Body :: map(), Req :: dgiot_req:req()}.
|
||||
|
||||
handle(OperationID, Args, Context, Req) ->
|
||||
Headers = #{},
|
||||
case catch do_request(OperationID, Args, Context, Req) of
|
||||
{ErrType, Reason} when ErrType == 'EXIT'; ErrType == error ->
|
||||
?LOG(info, "do request: ~p, ~p, ~p~n", [OperationID, Args, Reason]),
|
||||
Err = case is_binary(Reason) of
|
||||
true -> Reason;
|
||||
false ->
|
||||
dgiot_ctl:format("~p", [Reason])
|
||||
end,
|
||||
{500, Headers, #{<<"error">> => Err}};
|
||||
ok ->
|
||||
%% ?LOG(debug,"do request: ~p, ~p ->ok ~n", [OperationID, Args]),
|
||||
{200, Headers, #{}, Req};
|
||||
{ok, Res} ->
|
||||
%% ?LOG(info,"do request: ~p, ~p ->~p~n", [OperationID, Args, Res]),
|
||||
{200, Headers, Res, Req};
|
||||
{Status, Res} ->
|
||||
%% ?LOG(info,"do request: ~p, ~p ->~p~n", [OperationID, Args, Res]),
|
||||
{Status, Headers, Res, Req};
|
||||
{Status, NewHeaders, Res} ->
|
||||
%% ?LOG(info,"do request: ~p, ~p ->~p~n", [OperationID, Args, Res]),
|
||||
{Status, maps:merge(Headers, NewHeaders), Res, Req}
|
||||
end.
|
||||
|
||||
|
||||
%%%===================================================================
|
||||
%%% 内部函数 Version:API版本
|
||||
%%%===================================================================
|
||||
|
||||
|
||||
%% PumpTemplet 概要: 新增报告模板 描述:新增报告模板
|
||||
%% OperationId:post_pump_templet
|
||||
%% 请求:get /iotapi/pump/templet
|
||||
%% 服务器不支持的API接口
|
||||
do_request(_OperationId, _Args, _Context, _Req) ->
|
||||
{error, <<"Not Allowed.">>}.
|
@ -0,0 +1,256 @@
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @author kenneth
|
||||
%%% @copyright (C) 2018, <COMPANY>
|
||||
%%% @doc
|
||||
%%%
|
||||
%%% @end
|
||||
%%% Created : 07. 五月 2021 12:00
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
-module(dgiot_xinchuangwei_decoder).
|
||||
-author("stoneliu").
|
||||
-include_lib("dgiot/include/logger.hrl").
|
||||
|
||||
%%-record(rtu_req, {slaveId, funcode, address, quality}).
|
||||
-include("dgiot_xinchuangwei.hrl").
|
||||
%%
|
||||
-export([parse_frame/2, crc16/1, to_status_frame/1, set_params/2]).
|
||||
|
||||
%设置参数 返回
|
||||
parse_frame(<<16#AA, 16#11>>, _State) ->
|
||||
{<<>>, <<>>};
|
||||
|
||||
%读取参数 字典
|
||||
parse_frame(<<16#AA, 16#12, Addr:8, Len:8, Rest/binary>>, #state{dtuproduct = ProductId, devaddr = DevAddr}) ->
|
||||
case Rest of
|
||||
<<UserZone:Len/bytes, Crc:1/binary, _Rest1/binary>> ->
|
||||
CheckBuf = <<16#AA, 16#12, Addr:8, Len:8, UserZone/binary>>,
|
||||
CheckCrc = crc16(CheckBuf),
|
||||
case <<CheckCrc>> =:= Crc of
|
||||
true ->
|
||||
#{<<"objectId">> := DeviceId} =
|
||||
dgiot_parse:get_objectid(<<"Device">>, #{<<"product">> => ProductId, <<"devaddr">> => DevAddr}),
|
||||
case dgiot_parse:get_object(<<"Product">>, ProductId) of
|
||||
{ok, #{<<"config">> := #{<<"basedate">> := #{<<"params">> := Params}}}} ->
|
||||
case dgiot_parse:get_object(<<"Device">>, DeviceId) of
|
||||
{ok, #{<<"basedata">> := OldBasedata}} ->
|
||||
NewBasedata =
|
||||
lists:foldl(fun(X, Acc) ->
|
||||
case X of
|
||||
#{<<"identifier">> := Identifier,
|
||||
<<"protocol">> := <<"xinchuangwei">>,
|
||||
<<"address">> := <<"0">>,
|
||||
<<"type">> := Type,
|
||||
<<"bytes">> := Size,
|
||||
<<"unit">> := _Unit,
|
||||
<<"struct">> := Struct,
|
||||
<<"collection">> := Collection} ->
|
||||
NewSize = dgiot_utils:to_int(Size) * 8,
|
||||
<<Value:NewSize, _/binary>> = UserZone,
|
||||
Newvalue = check_field(Value, #{<<"type">> => Type, <<"struct">> => Struct}, <<"计算值"/utf8>>, Collection),
|
||||
Acc#{Identifier => Newvalue};
|
||||
#{<<"identifier">> := Identifier,
|
||||
<<"protocol">> := <<"xinchuangwei">>,
|
||||
<<"address">> := Address,
|
||||
<<"type">> := Type,
|
||||
<<"bytes">> := Size,
|
||||
<<"unit">> := _Unit,
|
||||
<<"struct">> := Struct,
|
||||
<<"collection">> := Collection} ->
|
||||
NewAddress = dgiot_utils:to_int(Address),
|
||||
NewSize = dgiot_utils:to_int(Size) * 8,
|
||||
<<_Befovalue:NewAddress/bytes, Value:NewSize, _/binary>> = UserZone,
|
||||
Newvalue = check_field(Value, #{<<"type">> => Type, <<"struct">> => Struct}, <<"计算值"/utf8>>, Collection),
|
||||
Acc#{Identifier => Newvalue};
|
||||
_ ->
|
||||
Acc
|
||||
end
|
||||
end, #{}, Params),
|
||||
?LOG(info, "OldBasedata: ~p", [OldBasedata]),
|
||||
?LOG(info, "NewBasedata: ~p", [NewBasedata]),
|
||||
Basedata = maps:merge(OldBasedata, NewBasedata),
|
||||
?LOG(info, "Basedata: ~p", [Basedata]),
|
||||
dgiot_parse:update_object(<<"Device">>, DeviceId, #{<<"status">> => <<"ONLINE">>, <<"basedata">> => Basedata}),
|
||||
{{params, Basedata}};
|
||||
_ ->
|
||||
?LOG(info, "NoDevice: ~p", [DeviceId]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
_ ->
|
||||
?LOG(info, "NoProduct: ~p", [ProductId]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
false ->
|
||||
?LOG(info, "CheckCrc ~p != Crc: ~p", [CheckCrc, Crc]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
_ ->
|
||||
?LOG(info, "Rest ~p", [Rest]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
|
||||
%%读取状态 物模型
|
||||
parse_frame(<<16#AA, 16#13, Addr:8, Len:8, Rest/binary>>, #state{dtuproduct = ProductId}) ->
|
||||
case Rest of
|
||||
<<UserZone:Len/bytes, Crc:1/binary, _Rest1/binary>> ->
|
||||
CheckBuf = <<16#AA, 16#13, Addr:8, Len:8, UserZone/binary>>,
|
||||
CheckCrc = crc16(CheckBuf),
|
||||
case <<CheckCrc>> =:= Crc of
|
||||
true ->
|
||||
case dgiot_device:lookup_prod(ProductId) of
|
||||
{ok, #{<<"thing">> := #{<<"properties">> := Props}}} ->
|
||||
Ack = lists:foldl(fun(X, Acc) ->
|
||||
case X of
|
||||
#{<<"identifier">> := Identifier,
|
||||
<<"dataForm">> := #{
|
||||
<<"protocol">> := <<"xinchuangwei">>,
|
||||
<<"address">> := <<"0">>,
|
||||
<<"data">> := Size}} ->
|
||||
NewSize = dgiot_utils:to_int(Size) * 8,
|
||||
<<Value:NewSize, _/binary>> = UserZone,
|
||||
Acc#{Identifier => Value};
|
||||
#{<<"identifier">> := Identifier,
|
||||
<<"dataForm">> := #{
|
||||
<<"protocol">> := <<"xinchuangwei">>,
|
||||
<<"address">> := Address,
|
||||
<<"data">> := Size}} ->
|
||||
NewAddress = dgiot_utils:to_int(Address),
|
||||
NewSize = dgiot_utils:to_int(Size) * 8,
|
||||
<<_Befovalue:NewAddress/bytes, Value:NewSize, _/binary>> = UserZone,
|
||||
Acc#{Identifier => Value};
|
||||
_Other ->
|
||||
%% ?LOG(info, "_Other ~p", [_Other]),
|
||||
Acc
|
||||
end
|
||||
end, #{}, Props),
|
||||
{status, Ack};
|
||||
_ ->
|
||||
?LOG(info, "NoProduct: ~p", [ProductId]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
false ->
|
||||
?LOG(info, "CheckCrc ~p != Crc: ~p", [CheckCrc, Crc]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
_ ->
|
||||
?LOG(info, "Addr ~p", [Addr]),
|
||||
?LOG(info, "Len ~p", [Len]),
|
||||
?LOG(info, "Rest ~p", [Rest]),
|
||||
{<<>>, <<>>}
|
||||
end;
|
||||
|
||||
parse_frame(Buff, _State) ->
|
||||
?LOG(info, "Buff ~p", [Buff]),
|
||||
{error, <<>>}.
|
||||
|
||||
set_params(Basedata, ProductId) ->
|
||||
case dgiot_parse:get_object(<<"Product">>, ProductId) of
|
||||
{ok, #{<<"config">> := #{<<"basedate">> := #{<<"params">> := Params}}}} ->
|
||||
Payloads =
|
||||
lists:foldl(fun(X, Acc) ->
|
||||
case X of
|
||||
#{<<"identifier">> := Identifier,
|
||||
<<"protocol">> := <<"xinchuangwei">>,
|
||||
<<"address">> := <<"0">>,
|
||||
<<"bytes">> := 1,
|
||||
<<"setting">> := <<"%s">>} ->
|
||||
case maps:find(Identifier, Basedata) of
|
||||
error ->
|
||||
Acc;
|
||||
{ok, Value} when erlang:byte_size(Value) == 0 ->
|
||||
Acc;
|
||||
{ok, Value} ->
|
||||
Value1 = dgiot_utils:to_int(Value),
|
||||
Message = <<16#55, 16#01, 16#00, 16#01, Value1>>,
|
||||
Checksum = crc16(Message),
|
||||
Payload = <<Message/binary, Checksum>>,
|
||||
Acc ++ [Payload];
|
||||
_ ->
|
||||
Acc
|
||||
end;
|
||||
_ ->
|
||||
%% ?LOG(info,"X ~p", [X]),
|
||||
Acc
|
||||
end
|
||||
end, [], Params),
|
||||
%% Topic = <<"setParams/", ProductId/binary, "/", Devaddr/binary>>,
|
||||
Payloads;
|
||||
_ ->
|
||||
?LOG(info, "NoProduct: ~p", [ProductId]),
|
||||
pass
|
||||
end.
|
||||
|
||||
%% 发送读取状态物模型命令
|
||||
to_status_frame(ProductId) ->
|
||||
lists:foldl(fun({Address, Quality} = R, Acc) ->
|
||||
?LOG(info, "R ~p", [R]),
|
||||
<<H:8>> = dgiot_utils:hex_to_binary(Address),
|
||||
Quality1 = dgiot_utils:to_int(Quality),
|
||||
Message = <<16#55, 16#03, H, Quality1>>,
|
||||
Checksum = crc16(Message),
|
||||
Payload = <<Message/binary, Checksum>>,
|
||||
?LOG(info, "status Payload ~p", [Payload]),
|
||||
Acc ++ [Payload]
|
||||
end, [], status_encoder(ProductId)).
|
||||
|
||||
status_encoder(ProductId) ->
|
||||
case dgiot_device:lookup_prod(ProductId) of
|
||||
{ok, #{<<"thing">> := #{<<"properties">> := Props}}} ->
|
||||
lists:foldl(fun(X, Acc) ->
|
||||
case X of
|
||||
#{<<"dataForm">> := #{<<"address">> := Address,
|
||||
<<"protocol">> := <<"xinchuangwei">>,
|
||||
<<"data">> := Quantity}} ->
|
||||
Acc ++ [{Address, Quantity}];
|
||||
_ ->
|
||||
Acc
|
||||
end
|
||||
end, [], Props);
|
||||
_ ->
|
||||
[]
|
||||
end.
|
||||
|
||||
%% crc校验 16进制和
|
||||
%% 55030102 => 5b
|
||||
%% AA1301020102 => c3
|
||||
%% Check = <<CheckBuf/binary, CheckCrc/binary>>.
|
||||
%% <<16#55,16#02,16#36,16#00>>
|
||||
crc16(CheckBuf) when is_binary(CheckBuf) ->
|
||||
Z = lists:foldl(fun(X, Acc) ->
|
||||
Acc + X
|
||||
end, 0, [X || <<X:8>> <= CheckBuf]),
|
||||
<<_:24, Crc:8>> = <<Z:32>>,
|
||||
Crc.
|
||||
|
||||
check_field(Value, #{<<"type">> := Type, <<"specs">> := _Specs}, <<"20">>, <<"%s">>) ->
|
||||
Type1 = list_to_binary(string:to_upper(binary_to_list(Type))),
|
||||
case Type1 of
|
||||
<<"ENUM">> ->
|
||||
dgiot_utils:to_binary(Value);
|
||||
_ ->
|
||||
Value
|
||||
end;
|
||||
|
||||
check_field(Value, #{<<"type">> := Type, <<"struct">> := _Struct}, _Stage, <<"%s">>) ->
|
||||
Type1 = list_to_binary(string:to_upper(binary_to_list(Type))),
|
||||
case Type1 of
|
||||
<<"ENUM">> ->
|
||||
dgiot_utils:to_binary(Value);
|
||||
_ ->
|
||||
Value
|
||||
end;
|
||||
|
||||
check_field(Value, _DataType, <<"计算值"/utf8>>, Collection) ->
|
||||
Str = re:replace(Collection, "%s", "(" ++ dgiot_utils:to_list(Value) ++ ")", [global, {return, list}]),
|
||||
NewValue = dgiot_task:string2value(Str),
|
||||
dgiot_utils:to_float(NewValue / 1, 3);
|
||||
|
||||
check_field(Value, DataType, Strategy, Collection) ->
|
||||
?LOG(info, "Value ~p", [Value]),
|
||||
?LOG(info, "DataType ~p", [DataType]),
|
||||
?LOG(info, "strategy ~p", [Strategy]),
|
||||
?LOG(info, "Collection ~p", [Collection]),
|
||||
Value.
|
||||
|
@ -23,3 +23,4 @@
|
||||
{dgiot_niisten, {{enable_plugin_dgiot_niisten}}}.
|
||||
{dgiot_modbus, {{enable_plugin_dgiot_modbus}}}.
|
||||
{dgiot_group, {{enable_plugin_dgiot_group}}}.
|
||||
{dgiot_group, {{enable_plugin_dgiot_xinchuangwei}}}.
|
||||
|
@ -201,6 +201,7 @@ overlay_vars_rel(RelType) ->
|
||||
, {enable_plugin_dgiot_niisten, true}
|
||||
, {enable_plugin_dgiot_modbus, true}
|
||||
, {enable_plugin_dgiot_group, true}
|
||||
, {enable_plugin_dgiot_xinchuangwei, true}
|
||||
, {vm_args_file, VmArgs}
|
||||
].
|
||||
|
||||
@ -325,6 +326,7 @@ relx_plugin_apps_per_rel(cloud) ->
|
||||
, dgiot_niisten
|
||||
, dgiot_modbus
|
||||
, dgiot_group
|
||||
, dgiot_xinchuangwei
|
||||
];
|
||||
relx_plugin_apps_per_rel(edge) ->
|
||||
[].
|
||||
|
Loading…
Reference in New Issue
Block a user