|
| 1 | +/****************************************************************************** |
| 2 | + * # License |
| 3 | + * <b>Copyright 2022 Silicon Laboratories Inc. www.silabs.com</b> |
| 4 | + ****************************************************************************** |
| 5 | + * The licensor of this software is Silicon Laboratories Inc. Your use of this |
| 6 | + * software is governed by the terms of Silicon Labs Master Software License |
| 7 | + * Agreement (MSLA) available at |
| 8 | + * www.silabs.com/about-us/legal/master-software-license-agreement. This |
| 9 | + * software is distributed to you in Source Code format and is governed by the |
| 10 | + * sections of the MSLA applicable to Source Code. |
| 11 | + * |
| 12 | + *****************************************************************************/ |
| 13 | +#include "multilevel_sensor_cluster_server.h" |
| 14 | +#include "zcl_cluster_servers_helpers.hpp" |
| 15 | + |
| 16 | +// Interfaces |
| 17 | +#include "zwave_command_class_version_types.h" |
| 18 | +#include "zwave_command_class_configuration_types.h" |
| 19 | + |
| 20 | +// ZPC includes |
| 21 | +#include "zpc_attribute_store.h" |
| 22 | +#include "zpc_attribute_store_network_helper.h" |
| 23 | +#include "zwave_command_class_generic_types.h" |
| 24 | +#include "attribute_store_defined_attribute_types.h" |
| 25 | + |
| 26 | +// Includes from Unify shared components |
| 27 | +#include "attribute.hpp" |
| 28 | +#include "attribute_store_helper.h" |
| 29 | +#include "sl_log.h" |
| 30 | + |
| 31 | +// Includes from auto-generated files |
| 32 | +#include "dotdot_mqtt.h" |
| 33 | +#include "zap-types.h" |
| 34 | +#include "dotdot_mqtt_helpers.hpp" |
| 35 | + |
| 36 | +// Generic includes |
| 37 | +#include <string> |
| 38 | +#include <stdlib.h> |
| 39 | +#include <vector> |
| 40 | + |
| 41 | +using namespace attribute_store; |
| 42 | + |
| 43 | +// Setup Log ID |
| 44 | +constexpr char LOG_TAG[] = "multilevel_sensor_cluster_server"; |
| 45 | + |
| 46 | +// Attribute macro, shortening those long defines for attribute types: |
| 47 | +#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_SENSOR_MULTILEVEL_##type |
| 48 | + |
| 49 | +// List of attributes of SensorValues |
| 50 | +namespace |
| 51 | +{ |
| 52 | +const std::vector<attribute_store_type_t> sensor_values_attributes |
| 53 | + = {ATTRIBUTE(SENSOR_VALUE), ATTRIBUTE(SCALE)}; |
| 54 | +} |
| 55 | + |
| 56 | +/////////////////////////////////////////////////////////////////////////////// |
| 57 | +// Attribute publication functions |
| 58 | +////////////////////////////////////////////////////////////////////////////// |
| 59 | + |
| 60 | +/** |
| 61 | + * @brief Publishes the Multilevel Sensor Cluster Server attributes |
| 62 | + * |
| 63 | + * @param unid unid for which we want to publish the |
| 64 | + * SensorValues attributes. |
| 65 | + * @param endpoint_id Endpoint ID for which we want to publish the |
| 66 | + * SensorValues attributes. |
| 67 | + * @param sensor_type Sensor Type node ID for which we want to publish the |
| 68 | + * SensorValues attributes. |
| 69 | + */ |
| 70 | +static sl_status_t publish_multilevel_sensor_cluster_attributes( |
| 71 | + const std::string &unid, |
| 72 | + attribute_store::attribute sensor_type_node, |
| 73 | + zwave_endpoint_id_t endpoint_id) |
| 74 | +{ |
| 75 | + // Do not publish any state supported commands for ourselves. |
| 76 | + if (is_zpc_unid(unid.c_str())) { |
| 77 | + return SL_STATUS_FAIL; |
| 78 | + } |
| 79 | + |
| 80 | + // Build the base topic and pass it on to DotDot MQTT. |
| 81 | + try { |
| 82 | + // Get reported sensor type ID |
| 83 | + uint8_t sensor_type = sensor_type_node.reported<uint8_t>(); |
| 84 | + |
| 85 | + // Get SensorType name |
| 86 | + const std::string sensor_type_str |
| 87 | + = multilevel_sensor_sensor_type_get_enum_value_name(sensor_type); |
| 88 | + |
| 89 | + // Added sensor type name to base topic |
| 90 | + const std::string base_topic = "ucl/by-unid/" + std::string(unid) + "/ep" |
| 91 | + + std::to_string(endpoint_id) + "/" |
| 92 | + + std::string(sensor_type_str); |
| 93 | + |
| 94 | + SensorValue value = {0, 0}; |
| 95 | + // Get report sensor value |
| 96 | + attribute_store::attribute sensor_value_node |
| 97 | + = sensor_type_node.child_by_type(ATTRIBUTE(SENSOR_VALUE)); |
| 98 | + if (sensor_value_node.reported_exists()) { |
| 99 | + value.Value = sensor_value_node.reported<int32_t>(); |
| 100 | + } |
| 101 | + // Get report sensor scale |
| 102 | + attribute_store::attribute sensor_scale_node |
| 103 | + = sensor_type_node.child_by_type(ATTRIBUTE(SCALE)); |
| 104 | + if (sensor_scale_node.reported_exists()) { |
| 105 | + value.Scale = static_cast<uint8_t>(sensor_scale_node.reported<int32_t>()); |
| 106 | + } |
| 107 | + |
| 108 | + // Pulish the sensor value attribute |
| 109 | + if (SL_STATUS_OK |
| 110 | + != uic_mqtt_dotdot_multilevel_sensor_sensor_values_publish( |
| 111 | + base_topic.c_str(), |
| 112 | + value, |
| 113 | + UCL_MQTT_PUBLISH_TYPE_REPORTED)) { |
| 114 | + return SL_STATUS_FAIL; |
| 115 | + } |
| 116 | + } catch (const std::exception &e) { |
| 117 | + sl_log_error(LOG_TAG, |
| 118 | + "Error while get base topic and sensor data : %s", |
| 119 | + e.what()); |
| 120 | + |
| 121 | + return SL_STATUS_FAIL; |
| 122 | + } |
| 123 | + return SL_STATUS_OK; |
| 124 | +} |
| 125 | + |
| 126 | +/////////////////////////////////////////////////////////////////////////////// |
| 127 | +// Attribute store callback functions |
| 128 | +////////////////////////////////////////////////////////////////////////////// |
| 129 | +/** |
| 130 | + * @brief Listens to updates to the SensorValues then publishes the attributes. |
| 131 | + * |
| 132 | + * @param updated_node Attribute Store node that was modified. |
| 133 | + * @param change Type of change applied to the node. |
| 134 | + */ |
| 135 | +void on_sensor_values_update(attribute_store_node_t updated_node, |
| 136 | + attribute_store_change_t change) |
| 137 | +{ |
| 138 | + if (change == ATTRIBUTE_CREATED || change == ATTRIBUTE_DELETED) { |
| 139 | + return; |
| 140 | + } |
| 141 | + |
| 142 | + // Go up and find the UNID/Endpoint and its network status. |
| 143 | + unid_t unid; |
| 144 | + zwave_endpoint_id_t endpoint_id = 0; |
| 145 | + if (SL_STATUS_OK |
| 146 | + != attribute_store_network_helper_get_unid_endpoint_from_node( |
| 147 | + updated_node, |
| 148 | + unid, |
| 149 | + &endpoint_id)) { |
| 150 | + return; |
| 151 | + } |
| 152 | + |
| 153 | + attribute_store::attribute sensor_type_node |
| 154 | + = attribute_store_get_first_parent_with_type(updated_node, |
| 155 | + ATTRIBUTE(SENSOR_TYPE)); |
| 156 | + |
| 157 | + // Publish the multilevel sensor values: |
| 158 | + if (SL_STATUS_OK |
| 159 | + != publish_multilevel_sensor_cluster_attributes(std::string(unid), |
| 160 | + sensor_type_node, |
| 161 | + endpoint_id)) { |
| 162 | + return; |
| 163 | + } |
| 164 | +} |
| 165 | + |
| 166 | +/////////////////////////////////////////////////////////////////////////////// |
| 167 | +// Init and teardown functions. |
| 168 | +////////////////////////////////////////////////////////////////////////////// |
| 169 | +sl_status_t multilevel_sensor_cluster_server_init(void) |
| 170 | +{ |
| 171 | + sl_log_debug(LOG_TAG, "Multilevel sensor server initialization"); |
| 172 | + |
| 173 | + // Register attribute updates |
| 174 | + |
| 175 | + attribute_store_register_callback_by_type_to_array( |
| 176 | + &on_sensor_values_update, |
| 177 | + sensor_values_attributes.data(), |
| 178 | + static_cast<uint32_t>(sensor_values_attributes.size())); |
| 179 | + |
| 180 | + return SL_STATUS_OK; |
| 181 | +} |
0 commit comments