[ST Edge] How to update/increase the number of endpoints?

I have a zigbee multi smart plug that keeps emitting/receiving messages from 4 endpoints, but it actually have 5.

I read in the API code, there are some references to zigbee_endpoints, but I don’t know how to update it.

So my question is in the title. Thanks in advance.

I don’t feel proud about myself but yeah, the following code did the trick… now it is keeping track of the statuses of all 5 endpoints by default, not only the first 4:

local utils = require('st.utils')
local json = require("dkjson")

local lifecycle_handler = {}

function lifecycle_handler.init(driver, device, event, args)
  local device_cloud = json.decode(driver.device_api.get_device_info(device.id))
  device_cloud.zigbee_endpoints = utils.merge({
    ["5"] = utils.merge({
      id = 5
    }, device_cloud.zigbee_endpoints["2"])
  }, device_cloud.zigbee_endpoints)
  device:load_updated_data(device_cloud)
}

return lifecycle_handler

Basically, the logic here is to copy the 2º endpoint (it could be any from 2 to 4) and place it in the 5º position of zigbee_endpoints.

Now, my endpoints are these (the bold one was included by the code above):


{
  1={
    client_clusters={
      1=25, 
      2=10, 
    }, 
    device_id=266, 
    id=1, 
    manufacturer="_TZ3000_o005nuxx", 
    model="TS011F", 
    profile_id=260, 
    server_clusters={
      1=0, 
      2=3, 
      3=4, 
      4=5, 
      5=6, 
      6=57344, 
      7=57345, 
    }, 
  }, 
  2={
    client_clusters={}, 
    device_id=266, 
    id=2, 
    profile_id=260, 
    server_clusters={
      1=3, 
      2=4, 
      3=5, 
      4=6, 
      5=57344, 
      6=57345, 
    }, 
  }, 
  3={
    client_clusters={}, 
    device_id=266, 
    id=3, 
    profile_id=260, 
    server_clusters={
      1=3, 
      2=4, 
      3=5, 
      4=6, 
      5=57344, 
      6=57345, 
    }, 
  }, 
  4={
    client_clusters={}, 
    device_id=266, 
    id=4, 
    profile_id=260, 
    server_clusters={
      1=3, 
      2=4, 
      3=5, 
      4=6, 
      5=57344, 
      6=57345, 
    }, 
  }, 
  5={
    client_clusters={}, 
    device_id=266, 
    id=5, 
    profile_id=260, 
    server_clusters={
      1=3, 
      2=4, 
      3=5, 
      4=6, 
      5=57344, 
      6=57345, 
    }, 
  }, 
}

I am still testing what is the best lifecycle handler to invoke this code.

This code doesn’t update endpoints in the cloud, just locally in the hub.
In other words, every time your code (or elsewhere in the native code) call get_device_info(device_id), it will receive the original 4 endpoints.

I won’t mark this post as the solution because I think there could be a cleaner/official way to update endpoints.

References:
st.Device.load_updated_data
st.utils.merge
Part XIII: Appendices - D. Custom Endpoints

2 Likes

Hi!
Can you provide more details, please?

Did you see the RX and TX messages of the reporting configuration for all the endpoints before the modification?

What do you mean by “in the cloud”? For example:

  • The component (endpoint) doesn’t appear in the device UI
  • The component appears in the app but it’s empty or the value is not updated

Can you share the configuration you made for the components in the driver, please?

What details you need?
It is a ZigBee Smart Multi-plug that works with 5 different endpoints.
They can be turned on and off independently.
By default, the fifth endpoint (USB plugs) isn’t recognized.


Yes, there were messages only for endpoints 1 to 4.
I confirmed it because I printed device.zigbee_endpoints in the log on each lifecycle handler and there were only 4 endpoints.

When I call driver.device_api.get_device_info(device_uuid), I think it returns a JSON from the cloud (SmartThings platform).
I can’t say for sure because we don’t have access to _envlibrequire("devices") and can’t check where this JSON came from.
driver.get_device_info(device_uuid, force_refresh) may return from the cache, depending on the parameters. It differs from the other one I informed before.
When I said “in the cloud”, I meant I always get 4 endpoints when calling driver.device_api.get_device_info(device_uuid) and I think currently there isn’t any way to update it.

Did you mean this?

local function component_to_endpoint(device, component_id)
  if component_id == "main" then
    return device.fingerprinted_endpoint_id
  else
    local ep_num = component_id:match("main_(%d)")
    return ep_num and tonumber(ep_num) or device.fingerprinted_endpoint_id
  end
end

local function endpoint_to_component(device, ep)
  if ep == device.fingerprinted_endpoint_id then
    return "main"
  else
    return string.format("main_%d", ep)
  end
end

...

device:set_component_to_endpoint_fn(component_to_endpoint)
device:set_endpoint_to_component_fn(endpoint_to_component)

After I modified device.zigbee_endpoints to include the fifth one, I started receiving its status and everything started working as expected.

I probably could have sent the BindRequest and ConfigureReporting by myself for the fifth endpoint without “messing” with zigbee_endpoints, but I wanted to make use of the default behavior from the API…

function ZigbeeDevice:configure()
  local configured_attrs = self:get_field(CONFIGURED_ATTRIBUTES_KEY) or {}
  for cluster, attrs in pairs(configured_attrs) do
    for _, ep in pairs(self.zigbee_endpoints) do
      if self:supports_server_cluster(cluster, ep.id) then
        self:send(device_management.build_bind_request(self, cluster, self.driver.environment_info.hub_zigbee_eui, ep.id):to_endpoint(ep.id))
        for _, config in pairs(attrs) do
          self:send(device_management.attr_config(self, config):to_endpoint(ep.id))
        end
      end
    end
  end

Anyway, the questions here are:

  • After calling driver.device_api.get_device_info(device_uuid), why zigbee_endpoints only returns 4 endpoints instead of 5? Hardware fault or API fault ?
  • If it is hardware fault, is there any other cleaner way to update/increase zigbee_endpoints ?

Ok, let me check some details with the engineering team and as soon as I get their feedback, I’ll share it with you.

1 Like

Following up, the team mentioned that your workaround is correct (thank you for sharing it!), and using it in the init lifecycle is the best bet for now.
The team will review the issue of recognizing only 4 endpoints, as soon as I get more information, I’ll share it with you :smiley:

3 Likes

Good Evening.
I am using Your driver with a multi plug which has endpoints 1,2,3,4,7. How can you avoid having endpoints 5 and 6 created?

  • id: “TS0115”
    manufacturer: _TYZB01_vkwryfdr
    model: TS0115

Thank you

could you paste data and raw description ? for example:

To avoid having 7 endpoints, you need to create only 5 and map the indexes accordingly.
I need the raw description because the fifth endpoint is created on-the-fly and requires some informations from the raw description.

I am intrigated… If you don’t mind, how you used my driver that is supposed to pair with _TZ3000_o005nuxx/TS011F only ?

The driver works fine with my multi plugs (except ep 5 and 6), creating child devices was great for edge. Of course I would just like to adapt it better to my device.

  • endpointId: 01
  • manufacturer: _TYZB01_vkwryfdr
  • model: TS0115
  • zigbeeNodeType: ROUTER |
    |Raw Description|01 0104 0009 00 05 0000 000A 0004 0005 0006 01 0019|

I have updated it to work with your device. Could you please test it ?

Invitation : https://api.smartthings.com/invite/6Vjd4YPVJwjN

Thank you.
The Main device is ok with the 2,3,4,7 devices inside.
The child devices it creates are 2,3,4,5 and the child device 5 does not work

Are you sure ?
It is supposed to have all 5 endpoints inside of the main device… Main, Main_2, Main_3, Main_4, Main_7 (not in this order)
The child devices created should be 2,3,4 and 7

  • How do you know the child devices created were 2,3,4 and 5 ?
  • Have you removed all old devices/child devices one by one before repairing with the new driver ?
  • Do you have 2 or more drivers installed that work with your device ?
  • Was it paired automatically with the driver I developed ?

Lua is entirely new to me.
It is strange how it deals with indexed arrays.
I don’t know if I could have indexed array with keys 1,2,3,4 and 7, for example
I will test it.

UPDATE
I found the error. I will fix in a minute.


I have tried everything. is always the same

Ah, now I understand how you presumed it was for endpoint 5… It will show “Child Smart Plug 5” because there are only 5 endpoints, but the fifth is for endpoint 7 in your case.

I just updated the code. I don’t know whether you need to install again or just repair the device.

Ok . Thank you. It work veri well Now.

Did you install again or repair the device?

i deleted and reinstalled the driver. then I paired the device

Date
application: 43
endpointId: 01
manufacturer: _TYZB01_b1ngbmlm
model: TS0112
zigbeeNodeType: ROUTER
Raw Description
01 0104 0051 00 07 0000 0003 0004 0005 0006 0702 0B04 01 0019

Could you also add this device?
It only has two endpoints 1 and 2

Based on the raw description, it seems completely different from the others.
0702 = Simple Metering
0B04 = Electrical Measurement

I don’t have any device with these clusters. Can’t help you this time.
It could have the basic functionalities, but it would lose others.