I have water leakage protection system called “Neptun Smart” with tuya controller. I haven’t been able to find info how to configure HA to use it so I decided to share my experience.
Using “Tuya API Explorer - Query Things Data Model” I have been able to get code descriptions and using LocalTuya added a new device. Unfortunately I haven’t found the way to share device profile cause LocalTuya doesn’t use YAML configuration anymore.
Protocol version 3.3
I haven’t been able to insert table so share original json using code.
{
"result":{
"model":{
"modelId":"000002fhoc",
"services":[
{
"actions":[
],
"code":"",
"description":"",
"events":[
],
"name":"默认服务",
"properties":[
{
"abilityId":101,
"accessMode":"rw",
"code":"floor_cleaning_flag",
"description":"Implemented as a switch in the settings window",
"extensions":{
"iconName":"icon-dp_water",
"attribute":"4"
},
"name":"Floor cleaning",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":108,
"accessMode":"rw",
"code":"add_new_sensors",
"description":"Flag of starting procedure of add new sensors. Define as button in Sensor settings window.",
"name":"Add new sensors",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":109,
"accessMode":"rw",
"code":"status_crane_group_1",
"description":"Status of crane first group. Define as switch in main window of app",
"extensions":{
"iconName":"icon-icon-test10",
"attribute":"5"
},
"name":"Status crane group 1",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":110,
"accessMode":"rw",
"code":"status_crane_group_2",
"description":"Status of crane second group. Define as switch in main window of app",
"extensions":{
"iconName":"icon-icon-test10",
"attribute":"5"
},
"name":"Status crane group 2",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":111,
"accessMode":"rw",
"code":"group_eneble",
"description":"Enable separate on two group. Define as switch in config window",
"name":"Group enable",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":112,
"accessMode":"rw",
"code":"close_if_sensor_loss",
"description":"Enable of closing cranes on loss of RF sensors . Define as switch in config window.",
"name":"Close if sensor loss",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":113,
"accessMode":"rw",
"code":"child_protection",
"description":"If enabled then keyboard is blocked. Define in config window as switch.",
"extensions":{
"iconName":"icon-dp_lock",
"attribute":"4"
},
"name":"Child protection",
"typeSpec":{
"type":"bool"
}
},
{
"abilityId":114,
"accessMode":"rw",
"code":"line_settings",
"description":"Settings for four lines.\n{input_type_1, control_group_1 },\n{input_type_2, control_group_2 },\n{input_type_3, control_group_3 },\n{input_type_4, control_group_4 }\n\ninput_type - byte, ref. as (0-sensor/1-key)\ncontrol_group - byte, ref. as (1-control group 1; 2-control group 2; 3-control both group)\n",
"name":"Line settings",
"typeSpec":{
"type":"raw",
"maxlen":128
}
},
{
"abilityId":115,
"accessMode":"ro",
"code":"status_wire_line",
"description":"Status each from four wire lines.\n{status_line_1, status_line_2, status_line_3, status_line_4}\nEach status_line is а boolean. Use for notifications.",
"name":"Status wire line",
"typeSpec":{
"type":"value",
"max":255,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":116,
"accessMode":"rw",
"code":"relay_settings",
"description":"Configuring relay triggering by events.\n{event_close, event_attention}\nevent_close - byte, can referenced as 0 - not triggered; 1- triggered if close crane 1 group; 2-if close crane 2 group; 3 - if close crane both group.\nevent_attention - byte, can referenced as 0 - not triggered; 1- triggered if attention on 1 group; 2- if attention on 2 group; 3 - if both group.\n\n\n",
"name":"Relay settings",
"typeSpec":{
"type":"value",
"max":15,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":117,
"accessMode":"rw",
"code":"address_modbus",
"description":"Address MODBUS RTU for extender module RS-485. Defined in settings menu",
"name":"Address MODBUS",
"typeSpec":{
"type":"value",
"max":247,
"min":1,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":118,
"accessMode":"rw",
"code":"modbus_speed",
"description":"Settings speed of MODBUS RTU. Defined in settings menu",
"name":"MODBUS speed",
"typeSpec":{
"type":"enum",
"range":[
"1200",
"2400",
"4800",
"9600",
"19200",
"38400",
"57600",
"115200",
"230400",
"460800",
"921600"
]
}
},
{
"abilityId":119,
"accessMode":"rw",
"code":"count_rf_sensors",
"description":"Counter of RF sensors. This value use for viewing window of configuration RF sensors.",
"name":"Count of RF sensors",
"typeSpec":{
"type":"value",
"max":50,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":120,
"accessMode":"rw",
"code":"settings_rf_sensors",
"description":"Massive of settings RF sensors. Max size of massive is 50. \nSettings is defined control leakage on group.\n{settings_rf_sensors} - data as 3 bytes for each sensor.\nReferenced as:\naddress of sensor - 2 bytes\ngroup connection - 1 byte, referenced as:\n 1 - first group\n 2 - second group\n 3 - both group",
"name":"Settings RF sensors",
"typeSpec":{
"type":"raw",
"maxlen":128
}
},
{
"abilityId":121,
"accessMode":"ro",
"code":"status_rf_sensor",
"description":"Massive of status RF sensors. Max size of massive is 50. \nEach element of massive consist five bytes.\n{\n battery_level (ref. 0-100),\n rf_signal_level (0 - 4),\n lost_sensor flag (0-1),\n discharge_battery_flag (0-1),\n attention_leakage_flag (0-1)\n} \n",
"name":"Status RF sensors",
"typeSpec":{
"type":"raw",
"maxlen":128
}
},
{
"abilityId":122,
"accessMode":"rw",
"code":"counters_data",
"description":"Data of counters for four slots.\n-Status counter n.m - 0/1 (byte)\n-Value of counter n.m - 0 -99999999 (4 bytes)\n-Step of counter n.m - 1,10,100 (byte)\n-Type of connection n.m - 0/1 (no namur/namur) (byte);\n-Error counter n.m - 0 -not, 1-short circuit, 2-brake (byte);\nn.m - n-slot(1-4), m - counter (1-2).\n",
"name":"Counters data",
"typeSpec":{
"type":"raw",
"maxlen":128
}
},
{
"abilityId":123,
"accessMode":"ro",
"code":"notifications",
"description":"Fault for notifications",
"extensions":{
"scope":"fault"
},
"name":"Notifications",
"typeSpec":{
"type":"bitmap",
"label":[
"alarm_1_group",
"alarm_2_group",
"sens_discharge",
"sensor_lost",
"close_1_group",
"close_2_group",
"cleaning_floor",
"slot1_error",
"slot2_error",
"slot3_error",
"slot4_error",
"counter1_error",
"counter2_error",
"counter3_error",
"counter4_error",
"counter5_error",
"counter6_error",
"counter7_error",
"counter8_error"
],
"maxlen":19
}
},
{
"abilityId":124,
"accessMode":"rw",
"code":"name_rf_1_5",
"description":"Name of sensors 1-5. Each name have size is 51 byte.",
"name":"Name RF sens 1-5",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":125,
"accessMode":"rw",
"code":"name_rf_6_10",
"description":"Names of senors 6-10. Each name have size is 51 byte.",
"name":"Name RF sens 6-10",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":126,
"accessMode":"rw",
"code":"name_rf_11_15",
"description":"Name of sensors 11-15. Each name have size is 51 byte.",
"name":"Name RF sens 11-15",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":127,
"accessMode":"rw",
"code":"name_rf_16_20",
"description":"Name of sensors 16-20",
"name":"Name RF sens 16-20",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":128,
"accessMode":"rw",
"code":"name_rf_20_25",
"description":"Name of sensors 20-25. Each name have size is 51 byte.",
"name":"Name RF sens 20-25",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":129,
"accessMode":"rw",
"code":"name_rf_26_30",
"description":"Name of sensors 26-30. Each name have size is 51 byte.",
"name":"Name RF sens 26-30",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":130,
"accessMode":"rw",
"code":"name_rf_31_35",
"description":"Name of sensors 31-35. Each name have size is 51 byte.",
"name":"Name RF sens 31-35",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":131,
"accessMode":"rw",
"code":"name_rf_36_40",
"description":"Name of sensors 36-40. Each name have size is 51 byte.",
"name":"Name RF sens 36-40",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":132,
"accessMode":"rw",
"code":"name_rf_40_45",
"description":"Name of sensors 40-50. Each name have size is 51 byte.",
"name":"Name RF sens 40-45",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":133,
"accessMode":"rw",
"code":"name_rf_46_50",
"description":"Name of sensors 45-50. Each name have size is 51 byte.",
"name":"Name RF sens 46-50",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":134,
"accessMode":"rw",
"code":"name_lines",
"description":"Name of wired lines. In array 4 names. Each name have size is 51 byte.",
"name":"Name of Lines",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":135,
"accessMode":"rw",
"code":"name_zones",
"description":"Name of zones. In array 2 names. Each name have size is 51 byte.",
"name":"Name of Zones",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":136,
"accessMode":"rw",
"code":"name_of_counters",
"description":"Names of counters. In array 8 names. Each name have size is 31 byte.",
"name":"Name of Counters",
"typeSpec":{
"type":"string",
"maxlen":255
}
},
{
"abilityId":137,
"accessMode":"ro",
"code":"counter1",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter1",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":138,
"accessMode":"ro",
"code":"counter2",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter2",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":139,
"accessMode":"ro",
"code":"counter3",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter3",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":140,
"accessMode":"ro",
"code":"counter4",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter4",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":141,
"accessMode":"ro",
"code":"counter5",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter5",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":142,
"accessMode":"ro",
"code":"counter6",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter6",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":143,
"accessMode":"ro",
"code":"counter7",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter7",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":144,
"accessMode":"ro",
"code":"counter8",
"description":"",
"extensions":{
"trigger":"direct"
},
"name":"Counter8",
"typeSpec":{
"type":"value",
"max":99999999,
"min":0,
"scale":0,
"step":1,
"unit":""
}
},
{
"abilityId":145,
"accessMode":"ro",
"code":"slots_map",
"description":"Slots map",
"name":"Slots map",
"typeSpec":{
"type":"raw",
"maxlen":128
}
}
]
}
]
}
},
"success":true,
"t":1717499666837,
"tid":"9adff8d8226311efb9a3028d4a92b5f0"
}
Automations
alias: Neptun - Unavailable
description: ""
trigger:
- platform: state
entity_id:
- switch.neptun_status_crane_group_1
to: unavailable
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Neptun become unavailable
mode: single
alias: Neptun - Crane group is opened
description: ""
trigger:
- platform: state
entity_id:
- switch.neptun_status_crane_group_1
- switch.neptun_status_crane_group_2
from: "off"
to: "on"
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Crane group is opened
mode: single
alias: Neptun - Crane group is closed
description: ""
trigger:
- platform: state
entity_id:
- switch.neptun_status_crane_group_1
- switch.neptun_status_crane_group_2
from: "on"
to: "off"
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Crane group is closed
mode: single
alias: Neptun - Floor cleaning mode enabled
description: ""
trigger:
- platform: state
entity_id:
- switch.neptun_floor_cleaning
from: "off"
to: "on"
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Floor cleaning mode enabled
mode: single
alias: Neptun - Floor cleaning 1h notification
description: ""
trigger:
- platform: state
entity_id:
- switch.neptun_floor_cleaning
to: "on"
for:
hours: 1
minutes: 0
seconds: 0
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Floor cleaning enabled 1 hour!
mode: single
alias: Neptun - Floor cleaning mode disabled
description: ""
trigger:
- platform: state
entity_id:
- switch.neptun_floor_cleaning
from: "on"
to: "off"
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Floor cleaning mode disabled
mode: single
alias: Neptun - Leakage notification
description: ""
trigger:
- platform: state
entity_id:
- sensor.neptun_notifications
to: "3"
condition: []
action:
- service: notify.notify
data:
title: Neptun Smart
message: Leakage detected
mode: single
alias: Neptun - Leakage fixed notification
description: ""
trigger:
- platform: state
entity_id:
- sensor.neptun_notifications
to: "0"
from: "3"
condition: []
action:
- service: notify.notify
data:
message: Leakage fixed
title: Neptun Smart
mode: single
I have tried to create device profile using tuya-local but it’s based on tinytuya and can get only DPS broadcasted by device (114,122,137-145). It looks like Tinytuya is only picking up seqno = 0 and localtuya is only picking up seqno = 1 and avoiding seqno = 0.
Received Payload: {'dps': {'114': 'AwMDAw=='}, 't': 1717564996}
Received Payload: {'dps': {'122': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='}, 't': 1717564996}
Received Payload: {'dps': {'137': 0}, 't': 1717564996}
Received Payload: {'dps': {'138': 0}, 't': 1717564996}
Received Payload: {'dps': {'139': 0}, 't': 1717564996}
Received Payload: {'dps': {'140': 0}, 't': 1717564996}
Received Payload: {'dps': {'141': 0}, 't': 1717564996}
Received Payload: {'dps': {'142': 0}, 't': 1717564996}
Received Payload: {'dps': {'143': 0}, 't': 1717564996}
Received Payload: {'dps': {'144': 0}, 't': 1717564996}
Received Payload: {'dps': {'145': 'Bf///w=='}, 't': 1717564996}
If you know how to improve this integration please share you thoughts.