diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..da62a8ccbb --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +build/ + +externals/ diff --git a/applications/dev_ui/dev_gui/CMakeLists.txt b/applications/dev_ui/dev_gui/CMakeLists.txt index 34fa5defb0..b6624d4de2 100644 --- a/applications/dev_ui/dev_gui/CMakeLists.txt +++ b/applications/dev_ui/dev_gui/CMakeLists.txt @@ -1,5 +1,5 @@ # Developer GUI install -find_program(YARN_EXECUTABLE "yarn" REQUIRED) +find_program(YARN_EXECUTABLE "yarnpkg" "yarn" REQUIRED) if(APPLE) set(NPM_TARGET macos-x64) @@ -27,7 +27,7 @@ add_custom_command( COMMAND cp -r ${ZAP_CURRENT_OUTPUT_DIR}/. . COMMAND ${YARN_EXECUTABLE} version --no-git-tag-version --new-version ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV} - COMMAND ${YARN_EXECUTABLE} install --allow-same-version + COMMAND ${YARN_EXECUTABLE} install COMMAND ${YARN_EXECUTABLE} run build USES_TERMINAL) diff --git a/applications/dev_ui/dev_gui/src/App.tsx b/applications/dev_ui/dev_gui/src/App.tsx index 65f5d9250e..4a834a6fd5 100644 --- a/applications/dev_ui/dev_gui/src/App.tsx +++ b/applications/dev_ui/dev_gui/src/App.tsx @@ -33,6 +33,7 @@ import Scene from './pages/scenes/scene/scene'; import EpScenes from './pages/scenes/ep-scenes/ep-scenes'; import { CommissionableDevices } from './pages/commissionable-devices/commissionable-devices'; import { Button, Modal, Spinner } from 'react-bootstrap'; +import UserCredential from './pages/user-credential/user-credential'; class App extends Component<{}, AppState> { constructor(props: {}) { @@ -148,6 +149,23 @@ class App extends Component<{}, AppState> { this.setState({ CommissionableDevices: list }); } + handleEvents(data: any) { + var toastType = toast.TYPE.DEFAULT; + switch (data.level) { + case 1: + toastType = toast.TYPE.INFO; + break; + case 2: + toastType = toast.TYPE.WARNING; + break; + case 3: + case 4: + toastType = toast.TYPE.ERROR; + break; + } + toast(data.message, { type: toastType }) + } + handleUPTIChange(list: any[]) { let upti = this.state.UPTI; upti.List = list; @@ -278,6 +296,7 @@ class App extends Component<{}, AppState> { } /> } /> } /> + } /> {Object.keys(ClusterTypes).map((type, index) => i.name === type)?.path} render={() => @@ -412,6 +431,9 @@ class App extends Component<{}, AppState> { case "commissionable-device": this.handleCommissionableDevices(mes.data); break; + case "event": + this.handleEvents(mes.data); + break; } } diff --git a/applications/dev_ui/dev_gui/src/dev-gui-api/handler.js b/applications/dev_ui/dev_gui/src/dev-gui-api/handler.js index f24aef987e..d633896eff 100644 --- a/applications/dev_ui/dev_gui/src/dev-gui-api/handler.js +++ b/applications/dev_ui/dev_gui/src/dev-gui-api/handler.js @@ -40,6 +40,20 @@ exports.processSmartStart = (topic, message) => { } } +exports.processEvent = (topic, message) => { + console.log(`Received Event : '${message}'`); + if (message.toString() == "") + return; + try { + return { + type: "event", + data: JSON.parse(message) + }; + } catch (error) { + return getErrorResponse(topic, message, error); + } +} + exports.processCluster = (topic, message) => { let index = -1; let match = topic.match(/ucl\/by-unid\/(.*)\/(ep\d+)\/(.*)/) diff --git a/applications/dev_ui/dev_gui/src/dev-gui-api/main.js b/applications/dev_ui/dev_gui/src/dev-gui-api/main.js index 43e80e8dc5..4d829d972f 100644 --- a/applications/dev_ui/dev_gui/src/dev-gui-api/main.js +++ b/applications/dev_ui/dev_gui/src/dev-gui-api/main.js @@ -33,7 +33,8 @@ let topics = ["ucl/SmartStart/List", "ucl/UPTICap/#", "ucl/by-machine-id/+/SystemMetrics/SupportedCommands", "ucl/by-machine-id/+/SystemMetrics/Attributes/#", - "ucl/by-mqtt-client/+/ApplicationMonitoring/Attributes/#" + "ucl/by-mqtt-client/+/ApplicationMonitoring/Attributes/#", + "ucl/Event" ]; Object.keys(supportedClusters).forEach((i) => { topics.push(`ucl/by-unid/+/+/${i}/SupportedCommands`); @@ -282,6 +283,8 @@ function onMqttMessage(topic, message) { response = handler.processAppMonitoringList(topic, message); } else if (topic.match(/ucl\/SmartStart\/CommissionableDevice\/(.*)/)) { response = handler.processCommissionableDevices(topic, message); + } else if (topic === "ucl/Event") { + response = handler.processEvent(topic, message); } if (response && Object.keys(response).length > 0) handler.addToQueue(response.type, response.data); diff --git a/applications/dev_ui/dev_gui/src/pages/base-clusters/cluster-view-overrides.tsx b/applications/dev_ui/dev_gui/src/pages/base-clusters/cluster-view-overrides.tsx index 852e21db37..45ac54c138 100644 --- a/applications/dev_ui/dev_gui/src/pages/base-clusters/cluster-view-overrides.tsx +++ b/applications/dev_ui/dev_gui/src/pages/base-clusters/cluster-view-overrides.tsx @@ -10,7 +10,7 @@ import { ClusterTypes } from '../../cluster-types/cluster-types'; import { ClusterViewOverride } from './base-cluster-types'; import { Link } from 'react-router-dom'; import { Tooltip } from '@mui/material'; -import { Button } from 'react-bootstrap'; +import { Button, Badge } from 'react-bootstrap'; //Here you can find icons that can be used to customize you page: https://react-icons.github.io/react-icons/ //Don`t forgot to check licence if you use something that is not in Licence.txt @@ -769,4 +769,23 @@ export let ClusterViewOverrides = { } as NavbarItem, IsExpandable: true } as ClusterViewOverride, + + UserCredential: { + NodesTooltip: (endpoint: string) => + + + + + + + , + NavbarItem: { + name: "User Credential", + title: 'User Credential', + path: '/usercredential', + icon: , + cName: 'nav-text', + subMenu: SideMenu.Actuators + } as NavbarItem + } as ClusterViewOverride, } \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/cred-dlg/cred-dlg-types.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/cred-dlg/cred-dlg-types.tsx new file mode 100644 index 0000000000..76e9c0e53e --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/cred-dlg/cred-dlg-types.tsx @@ -0,0 +1,10 @@ +export type UserDlgState = { + Command: any, + Unid: any, + ShowModal: boolean, + UserCredential: any +} + +export type UserDlgProps = { + SocketServer: WebSocket +} \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/cred-dlg/cred-dlg.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/cred-dlg/cred-dlg.tsx new file mode 100644 index 0000000000..638dd1b3f3 --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/cred-dlg/cred-dlg.tsx @@ -0,0 +1,110 @@ +import * as React from 'react'; +import { Button, Modal } from 'react-bootstrap'; +import { UserDlgProps, UserDlgState } from './cred-dlg-types'; +import UserCredentialAttrs from '../user-credential-attrs/user-credential-attrs'; + + +class CredDlg extends React.Component { + constructor(props: UserDlgProps) { + super(props); + this.sendCommand = this.sendCommand.bind(this); + this.toggleModal = this.toggleModal.bind(this); + this.state = { + Command: {}, + Unid: "", + ShowModal: false, + UserCredential: {} + }; + this.changeCommandAttrs = React.createRef(); + } + changeCommandAttrs: any; + + toggleModal(value: boolean) { + this.setState({ ShowModal: value }); + } + + getDefinedUserIDs(userCredential: any) { + var users = userCredential.User + if (!users) { + return []; + } + return Object.keys(users).map(user_id => { + return { label: user_id, id: parseInt(user_id) } + }); + } + + getSupportedEnum(enumData: any, supportedEnumField: any) { + if (!supportedEnumField) { + return enumData; + } + return enumData.filter((enumItem:any) => supportedEnumField[enumItem.name]); + } + + updateState(unid: string, command: any, showModal: boolean, userCredential: any) { + let updatedCommand = structuredClone(command); + + updatedCommand.fields = command.fields.map( (field: any) => { + switch (field.name) { + case "UserUniqueID": + field.values = this.getDefinedUserIDs(userCredential); + if (field.values.length !== 0) { + field.defaultValue = field.values[0]; + field.default = field.values[0].id; + } + break; + case "CredentialType": + field.enum = this.getSupportedEnum(field.enum, userCredential.SupportedCredentialTypes?.Reported); + break; + } + return field; + }); + + + updatedCommand.UserList = userCredential.User; + updatedCommand.UserCredential = userCredential; + + this.setState({ Unid: unid, Command: updatedCommand, ShowModal: showModal, UserCredential: userCredential }, + () => { + this.changeCommandAttrs.current.updateState(this.state.Command) + }); + + } + + sendCommand() { + if (this.state.UserCredential !== undefined) + this.props.SocketServer.send(JSON.stringify( + { + type: "run-cluster-command", + data: { + Unid: this.state.Unid, + ClusterType: "UserCredential", + Cmd: this.state.Command.name, + Payload: this.changeCommandAttrs.current.state.Payload + } + })); + } + + + render() { + return ( + this.toggleModal(false)}> + + {this.state.Command.name} + + + + + + + + + + ); + } +} + +export default CredDlg \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential-attrs/user-credential-attrs.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential-attrs/user-credential-attrs.tsx new file mode 100644 index 0000000000..005cca3dd1 --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential-attrs/user-credential-attrs.tsx @@ -0,0 +1,244 @@ +import * as React from 'react'; +import { Card, Form } from 'react-bootstrap'; +import * as FiIcons from 'react-icons/fi'; +import { Autocomplete, FormControlLabel, InputAdornment, MenuItem, Switch, TextField, Tooltip } from '@mui/material'; +import CommandAttrs from '../../../components/command-atts/command-attrs'; + +class UserCredentialAttrs extends CommandAttrs { + constructor(props: {}) { + super(props); + } + + + // If the command is trying to modify a user or credential, we update the payload with the current data + // Otherwise we only update the payload UserUniqueID + updatePayloadBasedOnUserData(userID : any, payload: any, commandName: string, userList: any, credentialType: any, credentialSlot: any) { + if (!userList) { + return payload; + } + + let modifyCommand = commandName.includes("Modify"); + let credentialCommand = commandName.includes("Credential"); + + if (modifyCommand) { + let user = userList[userID]; + if (credentialCommand) { + const userCred = user.Credential || {}; + const credType = userCred[credentialType] || {}; + const credSlot = credType[credentialSlot] || {}; + const credData = credSlot.CredentialData?.Reported || ""; + if (credData) { + payload.CredentialData = credData; + } else { + payload.CredentialData = ""; + } + } else { + Object.keys(payload).forEach((key) => { + if (user[key]) { + payload[key] = user[key].Reported; + } + }); + } + } + + return payload; + } + + + updateCredentials(userUniqueId: any, credentialType: any, userList: any, currentPayload: any, command: any) { + var slotItem = command.fields.find((item: any) => item.name === "CredentialSlot"); + if (!slotItem) + return currentPayload; + + if (command.name.includes("Add")) { + slotItem.values = this.getAvailableSlots(command.UserCredential, userUniqueId, credentialType); + } else { + slotItem.values = this.getDefinedSlots(command.UserCredential, userUniqueId, credentialType); + } + const credentialSlot = slotItem.values[0]?.id || '' + let newPayload = this.updatePayloadBasedOnUserData(currentPayload.UserUniqueID, currentPayload, command.name, + userList, credentialType, credentialSlot); + newPayload["CredentialSlot"] = credentialSlot; + newPayload["CredentialType"] = credentialType; + + return newPayload; + } + // Called when the User ID changes in the modal + onValueChange(valueObject: any, name: string) { + if (!valueObject) { + return; + } + + let commandName = this.state.Command?.name; + let userList = this.state.Command?.UserList; + let currentPayload = this.state.Payload; + const rawValue = valueObject.value?.id || valueObject.id; + + if (!commandName || !userList) { + return; + } + + let newPayload = []; + switch(name) { + case "UserUniqueID": + if (commandName.includes("Credential")) { + newPayload = this.updateCredentials(rawValue, this.state.Payload.CredentialType, userList, currentPayload, this.state.Command); + } + + // Update the payload based on the user ID + newPayload = this.updatePayloadBasedOnUserData(rawValue, newPayload.length == 0 ? currentPayload : newPayload, commandName, userList, currentPayload.CredentialType, currentPayload.CredentialSlot); + + newPayload["UserUniqueID"] = rawValue; + this.setState({ Payload: newPayload }); + break; + case "CredentialType": + const userUniqueId = this.state.Payload.UserUniqueID; + const credentialType = rawValue; + newPayload = this.updateCredentials(userUniqueId, credentialType, userList, currentPayload, this.state.Command); + // Needed in case we don't have a CredentialSlot/UserId field + newPayload["CredentialType"] = credentialType; + this.setState({ Payload: newPayload, Command: this.state.Command }); + break; + case "CredentialSlot": + const credentialSlot = rawValue; + newPayload = this.updatePayloadBasedOnUserData(currentPayload.UserUniqueID, currentPayload, commandName, userList, currentPayload.CredentialType, credentialSlot); + newPayload["CredentialSlot"] = credentialSlot; + this.setState({ Payload: newPayload }); + break; + } + } + + getAutocompleteValue(payloadValue:any) { + return {label: payloadValue+"", id: payloadValue}; + } + + getAvailableSlots(userCredentials: any, currentUserID: any, credentialType: any) { + + var availableSlot = []; + var credentialTypeName = credentialType || "default"; + var currentCredentialRule = userCredentials.Credentials[credentialTypeName] || {}; + var maxSlot = currentCredentialRule.SupportedSlotCount?.Reported || 10; + var userObject = userCredentials.User || {}; + var credentials = userObject[currentUserID]?.Credential || {}; + var currentUserSlots = credentials[credentialType] || {}; + + for (let i = 1; i <= maxSlot; i++) { + if (currentUserSlots[i] === undefined) { + availableSlot.push({label: i +"", id: i}); + } + } + + return availableSlot; + } + getDefinedSlots(userCredential: any, currentUserID: any, credentialType: any) { + var userObject = userCredential.User || {}; + var credentials = userObject[currentUserID]?.Credential || {}; + var currentUserSlots = credentials[credentialType] || {}; + + return Object.keys(currentUserSlots).map( (slot_id) => ({label: slot_id +"", id: parseInt(slot_id)})) + } + + + // This is the default payload for the command + // We update it if we are modifying something + getPayload(command: any) { + let payload = super.getPayload(command); + + + if (command.name.includes("Credential")) { + payload = this.updateCredentials(payload.UserUniqueID, payload.CredentialType, command.UserList, payload, command); + } + + return this.updatePayloadBasedOnUserData(payload.UserUniqueID, payload, command.name, command.UserList, payload.CredentialType, payload.CredentialSlot); + } + + renderField = (item: any, payload: any, prefixNames: any[], index: any) => { + var validationRegex = "" + // Expire timeout minutes is only for DuressUser + if (item.name === "ExpiringTimeoutMinutes" && this.state.Payload?.UserType !== "DuressUser") { + return; + } + if ((item.name === "CredentialData" + && this.state.Payload?.CredentialType === "PINCode") || + item.name === "PINCode") { + validationRegex = "^[0-9]*$"; + } + + switch (item.type) { + case "number": + if (item.values) { + return ( +
+ this.onValueChange({value}, item.name)} + renderInput={(params) => } + /> +
+ ) + } + break; + case "boolean": + return ( +
+
+
+ } label={item.name} name={item.name} onChange={this.handleChange.bind(this, prefixNames, true, false)} /> +
+
+
+ ) + case "enum": + if (item.enum && item.enum.length) { + return ( +
+ { + if (item.name == "CredentialType") { + this.onValueChange({id: event.target.value}, item.name); + } else { + this.handleChange(prefixNames, false, false, event) + } + } + } + variant="outlined"> + {item.enum.map((j: any, ind: number) => { + return + {j.name} + + })} + +
+ ) + } + break; + } + return (
+ { + if (validationRegex !== "") { + if (!event.target.value.match(validationRegex)) { + return; + } + } + if (item.maxLength && item.maxLength < event.target.value.length) { + return + } + this.handleChange(prefixNames, false, item.type === "number", event) + }} + onFocus={(event: any) => event.target.select()} inputProps={ + { readOnly: this.state.ReadOnly } + } /> +
) + } +} + +export default UserCredentialAttrs \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential-types.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential-types.tsx new file mode 100644 index 0000000000..f1a2d96e13 --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential-types.tsx @@ -0,0 +1,10 @@ +export type UserCredentialProps = { + NodeList: any, + SocketServer: WebSocket, + IsConnected: boolean | null +} + +export type UserCredentialState = { + List: Map, + IsAllExpanded: boolean +} \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential.tsx new file mode 100644 index 0000000000..f1da4f0333 --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/user-credential.tsx @@ -0,0 +1,334 @@ +import React, { Fragment } from 'react'; +import * as FiIcons from 'react-icons/fi'; +import * as BsIcons from 'react-icons/bs'; +import * as RiIcons from 'react-icons/ri'; +import { Button, Col, Dropdown, DropdownButton, Row, Table, Badge, Modal} from 'react-bootstrap'; +import * as CgIcons from 'react-icons/cg'; +import { Link } from 'react-router-dom'; +import { UserCredentialProps, UserCredentialState } from './user-credential-types'; +import EditableAttribute from '../../components/editable-attribute/editable-attribute'; +import UserDlg from './user-dlg/user-dlg'; +import CredDlg from './cred-dlg/cred-dlg'; +import { ClusterTypeAttrs } from '../../cluster-types/cluster-type-attributes'; +import { Tooltip } from '@mui/material'; + + +export class UserCredential extends React.Component { + constructor(props: UserCredentialProps) { + super(props); + this.state = { + List: this.getList(this.props.NodeList), + IsAllExpanded: false + } + this.userCommandDlg = React.createRef(); + this.credCommandDlg = React.createRef(); + } + + userCommandDlg: any; + credCommandDlg: any; + UserCredentialType = "UserCredential"; + + // https://stackoverflow.com/questions/45167565/does-react-js-support-html5-datalist + // Datalist ? + // https://stackoverflow.com/questions/57401738/how-to-make-react-input-a-text-and-select + // Use custom modal and preSendCommand to send MQTT command + + preSendCommand(unid: string, endPoint: string, cmd: string) { + let command = ClusterTypeAttrs[this.UserCredentialType].server.commands.find((i: { name: string; }) => i.name === cmd); + if (!command) + return; + + if (command && command.fields && command.fields.length) { + let userCredential = this.state.List.get(unid + endPoint)?.UserCredential + // Order matter here, a credential command should display the credCommandDlg even if it contains "user" + if (command.name.includes("Credential") || command.name.includes("PIN")) { + this.credCommandDlg.current.updateState(`${unid}/${endPoint}`, command, true, userCredential); + } else if (command.name.includes("User")) { + this.userCommandDlg.current.updateState(`${unid}/${endPoint}`, command, true, userCredential); + } + } else + this.props.SocketServer.send(JSON.stringify( + { + type: "run-cluster-command", + data: { + Unid: `${unid}/${endPoint}`, + ClusterType: this.UserCredentialType, + Cmd: command.name, + Payload: {} + } + })); + } + + updateState(nodeList: any) { + this.setState({ List: this.getList(nodeList) }); + } + + getList(nodeList: any) { + let list = new Map(); + nodeList.forEach((item: any) => { + if (!item.ep) + return; + Object.keys(item.ep).forEach(ep => { + if (!item.ep[ep].Clusters?.UserCredential) + return; + let userCredential = item.ep[ep].Clusters?.UserCredential?.Attributes; + console.log("UserCredential : ", userCredential); + list.set(item.Unid + ep, { + Node: item, + EndPoint: ep, + UserCredential: userCredential, + IsExpanded: (this.state && this.state.List && this.state.List.get(item.Unid + ep)?.IsExpanded) ?? userCredential?.length < 3 + }); + }); + }); + return list; + } + + getUsersHeaders = () => { + return ( + UID + User Name + User Type + Credential Rule + User Active + ) + } + getUsersContents = (user_id: number, user: any) => { + return ( + <> + + {["Modifier Type : " + user.UserModifierType?.Reported ,
,"Modifier Node ID : " + user.UserModifierNodeId?.Reported]}}> + {user_id} +
+ + + + {user.UserName?.Reported} + + + + + {user.UserType?.Reported} + + + {user.CredentialRule?.Reported} + {user.UserActiveState?.Reported == 1 ? Active : Inactive} + + ); + } + + getBadges = (value: any) => { + return (value != null ?
+ {Object.entries(value).map( ([key, value]) => { + return value ? {key} : ''; + })} +
+ : "-"); + } + getSupportedCredentialType(credentialsTypes: any, credentialRules: any) { + return (credentialsTypes != null ?
+ {Object.entries(credentialsTypes).map(([credentialsType, supported]) => { + var currentCredentialRule = credentialRules[credentialsType] || {}; + var learnSupport = currentCredentialRule.LearnSupport?.Reported; + var supportedSlotCount = currentCredentialRule.SupportedSlotCount?.Reported; + var credMinLength = currentCredentialRule.CredentialMinLength?.Reported; + var credMaxLength = currentCredentialRule.CredentialMaxLength?.Reported; + + return supported ? ( + + , "Supported Slot Count : " + supportedSlotCount,
, "Credential Min Length : " + credMinLength,
, "Credential Max Length : " + credMaxLength]}> + {credentialsType} +
+
) + : ''; + })} +
+ : "-"); + } + + getCredentialsTable = (credential : any) => { + if (Object.keys(credential).length === 0) { + return (Not credential found) + } + return ( + + + + + + + + + + + + { + Object.entries(credential).map(([credentialType, slots], index) => { + var slotObjects = slots as object; + var slotCount = Object.keys(slotObjects).length; + return ( + <> + { + Object.entries(slotObjects).map(([slotID, slotData], index) => { + return (<> + + { index === 0 ? : <>} + + + + + + ) + }) + } + + ) + })} + +
Credential TypeCredential SlotCRBCredential Data
{credentialType} + {["Modifier Type : " + slotData.CredentialModifierType?.Reported,
, "Modifier Node ID : " + slotData.CredentialModifierNodeId?.Reported]}}> + {slotID} +
+
{slotData.CredentialReadBack?.Reported ? : } {slotData.CredentialData?.Reported}
+ + ) + } + + toggleIsAllExpanded = () => { + this.state.List.forEach((value: any, key: string) => { + value.IsExpanded = !this.state.IsAllExpanded; + }); + this.setState({ IsAllExpanded: !this.state.IsAllExpanded }); + } + + render() { + return ( + <> +

User Credential

+ {(this.state.List.size === 0 || !this.props.IsConnected) + ? + + No Content + + + : + + + + + + + + + + + + + + {[...this.state.List.values()].map((item: any, index: number) => { + + let isOffline = item.Node.NetworkStatus === "Offline" || item.Node.NetworkStatus === "Unavailable"; + let commands = item.Node.ep[item.EndPoint].Clusters.UserCredential.SupportedCommands && item.Node.ep[item.EndPoint].Clusters.UserCredential.SupportedCommands.filter((cmd: any) => cmd !== "WriteAttributes"); + let userList = item.UserCredential?.User || {}; + let userCount = Object.keys(userList).length; + return ( + + + + + + + + + + + + + + + + {userCount && item.IsExpanded + ? + ( + + ) + : + } + + + ) + })} + +
+ + {this.state.IsAllExpanded ? : } + + NodeMax UsersSupported User TypesSupported Credential TypesSupported Credential RulesAdmin PIN CodeSupported Commands
+ { item.IsExpanded = !item.IsExpanded; }} hidden={!userCount}> + {item.IsExpanded ? : } + + + {item.UserCredential?.SupportedUserUniqueIdentifiers?.Reported}{this.getBadges(item.UserCredential?.SupportedUserTypes?.Reported)}{this.getSupportedCredentialType(item.UserCredential?.SupportedCredentialTypes?.Reported, item.UserCredential?.Credentials)}{this.getBadges(item.UserCredential?.SupportedCredentialRules?.Reported)}{(item.UserCredential?.SupportAdminPinCode?.Reported) ? + + {item.UserCredential?.AdminPinCode?.Reported} + + : + } + + {commands && commands.length + ? + {commands.map((cmd: string, cmdIndex: number) => { + return ( + {cmd} + ) + }) + } + + : <>} +
+ + + {this.getUsersHeaders()} + + + {Object.entries(userList).map((user: any, indexParam: number) => { + var userId = user[0]; + var userObject = user[1]; + + if (!userObject) { + return; + } + + var credentials = userObject.Credential || {}; + + return ( + <> + + {this.getUsersContents(userId, userObject)} + + {this.getCredentialsTable(credentials)} + + ) + }) + } + + +
+
User Count: {userCount}
+ } + + + + + + + ) + }; +} + +export default UserCredential; \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/user-dlg/user-dlg-types.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/user-dlg/user-dlg-types.tsx new file mode 100644 index 0000000000..76e9c0e53e --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/user-dlg/user-dlg-types.tsx @@ -0,0 +1,10 @@ +export type UserDlgState = { + Command: any, + Unid: any, + ShowModal: boolean, + UserCredential: any +} + +export type UserDlgProps = { + SocketServer: WebSocket +} \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/src/pages/user-credential/user-dlg/user-dlg.tsx b/applications/dev_ui/dev_gui/src/pages/user-credential/user-dlg/user-dlg.tsx new file mode 100644 index 0000000000..7b04cff24e --- /dev/null +++ b/applications/dev_ui/dev_gui/src/pages/user-credential/user-dlg/user-dlg.tsx @@ -0,0 +1,130 @@ +import * as React from 'react'; +import { Button, Modal } from 'react-bootstrap'; +import { UserDlgProps, UserDlgState } from './user-dlg-types'; +import UserCredentialAttrs from '../user-credential-attrs/user-credential-attrs'; + + +class UserDlg extends React.Component { + constructor(props: UserDlgProps) { + super(props); + this.sendCommand = this.sendCommand.bind(this); + this.toggleModal = this.toggleModal.bind(this); + this.state = { + Command: {}, + Unid: "", + ShowModal: false, + UserCredential: {} + }; + this.changeCommandAttrs = React.createRef(); + } + changeCommandAttrs: any; + + toggleModal(value: boolean) { + this.setState({ ShowModal: value }); + } + + getAvailableUserID(userCredential: any) { + let availableUserID = [] + var users = userCredential.User || {} + let maxUsers = userCredential.SupportedUserUniqueIdentifiers.Reported; + for (let i = 1; i <= maxUsers; i++) { + if (users[i] === undefined) { + availableUserID.push({label: i +"", id: i}); + } + } + + return availableUserID; + } + + getDefinedUserIDs(userCredential: any) { + var users = userCredential.User + if (!users) { + return []; + } + return Object.keys(users).map(user_id => { + return { label: user_id, id: parseInt(user_id) } + }); + } + + getSupportedEnum(enumData: any, supportedEnumField: any) { + if (!supportedEnumField) { + return enumData; + } + return enumData.filter((enumItem:any) => supportedEnumField[enumItem.name]); + } + + updateState(unid: string, command: any, showModal: boolean, userCredential: any) { + let updatedCommand = structuredClone(command); + + updatedCommand.fields = command.fields.map( (field: any) => { + switch (field.name) { + case "UserUniqueID": + if (command.name.includes("Add")) { + field.values = this.getAvailableUserID(userCredential); + } else { + field.values = this.getDefinedUserIDs(userCredential); + } + if (field.values.length !== 0) { + field.defaultValue = field.values[0]; + field.default = field.values[0].id; + } + break; + case "UserType": + field.enum = this.getSupportedEnum(field.enum, userCredential.SupportedUserTypes?.Reported); + break; + case "CredentialRule": + field.enum = this.getSupportedEnum(field.enum, userCredential.SupportedCredentialRules?.Reported); + break; + case "UserActiveState": + field.default = true; + break; + } + return field; + }); + + updatedCommand.UserList = userCredential.User; + + this.setState({ Unid: unid, Command: updatedCommand, ShowModal: showModal, UserCredential: userCredential }, + () => { + this.changeCommandAttrs.current.updateState(this.state.Command) + }); + + } + + sendCommand() { + if (this.state.UserCredential !== undefined) + this.props.SocketServer.send(JSON.stringify( + { + type: "run-cluster-command", + data: { + Unid: this.state.Unid, + ClusterType: "UserCredential", + Cmd: this.state.Command.name, + Payload: this.changeCommandAttrs.current.state.Payload + } + })); + } + + render() { + return ( + this.toggleModal(false)}> + + {this.state.Command.name} + + + + + + + + + + ); + } +} + +export default UserDlg \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts index 4b19b6aaae..4f941ced13 100644 --- a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts +++ b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-type-attributes.ts @@ -1,8 +1,8 @@ //This file is generated automatically. Don't try to change something here. //To add support for new clusters, modify addon-helper.js //To change the stucture of the ClusterTypeAttrs, modify cluster-type-attributes.zapt - - + + //generate ClusterTypes export let ClusterTypeAttrs: any = { Basic: { @@ -15206,6 +15206,1021 @@ export let ClusterTypeAttrs: any = { ] } }, + UserCredential: { + server:{ + attributes: [ + { + id: 0, + name: "SupportedUserUniqueIdentifiers", + type: "number", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + }, + { + id: 1, + name: "SupportedCredentialRules", + type: "bitmap", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + bitmap: [ + { name: "Single", mask: 2, type: "boolean", offset: 1 }, + { name: "Dual", mask: 4, type: "boolean", offset: 2 }, + { name: "Triple", mask: 8, type: "boolean", offset: 3 } + ] + }, + { + id: 2, + name: "SupportedCredentialTypes", + type: "bitmap", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + bitmap: [ + { name: "PINCode", mask: 1, type: "boolean", offset: 0 }, + { name: "Password", mask: 2, type: "boolean", offset: 1 }, + { name: "RFIDCode", mask: 4, type: "boolean", offset: 2 }, + { name: "BLE", mask: 8, type: "boolean", offset: 3 }, + { name: "NFC", mask: 16, type: "boolean", offset: 4 }, + { name: "UWB", mask: 32, type: "boolean", offset: 5 }, + { name: "EyeBiometric", mask: 64, type: "boolean", offset: 6 }, + { name: "FaceBiometric", mask: 128, type: "boolean", offset: 7 }, + { name: "FingerBiometric", mask: 256, type: "boolean", offset: 8 }, + { name: "HandBiometric", mask: 512, type: "boolean", offset: 9 }, + { name: "UnspecifiedBiometric", mask: 1024, type: "boolean", offset: 10 } + ] + }, + { + id: 3, + name: "SupportedUserTypes", + type: "bitmap", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + bitmap: [ + { name: "GeneralUser", mask: 1, type: "boolean", offset: 0 }, + { name: "ProgrammingUser", mask: 8, type: "boolean", offset: 3 }, + { name: "NonAccessUser", mask: 16, type: "boolean", offset: 4 }, + { name: "DuressUser", mask: 32, type: "boolean", offset: 5 }, + { name: "DisposableUser", mask: 64, type: "boolean", offset: 6 }, + { name: "ExpiringUser", mask: 128, type: "boolean", offset: 7 }, + { name: "RemoteOnlyUser", mask: 512, type: "boolean", offset: 9 } + ] + }, + { + id: 4, + name: "SupportCredentialChecksum", + type: "boolean", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + }, + { + id: 5, + name: "SupportAdminPinCode", + type: "boolean", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + }, + { + id: 6, + name: "SupportAdminPinCodeDeactivation", + type: "boolean", + required: true, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + }, + { + id: 7, + name: "AdminPinCode", + type: "text", + required: false, + reportRequired: false, + sceneRequired: false, + writable: false, + isArray: false, + } + ], + commands: [ + { + id: 1, + name: "AddUser", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "UserType", + type: "enum", + isArray: false, + enum:[ + { + name: "GeneralUser", + value: 0 + }, + { + name: "ProgrammingUser", + value: 3 + }, + { + name: "NonAccessUser", + value: 4 + }, + { + name: "DuressUser", + value: 5 + }, + { + name: "DisposableUser", + value: 6 + }, + { + name: "ExpiringUser", + value: 7 + }, + { + name: "RemoteOnlyUser", + value: 9 + } + ], + }, + { + name: "UserActiveState", + type: "boolean", + isArray: false, + }, + { + name: "CredentialRule", + type: "enum", + isArray: false, + enum:[ + { + name: "Single", + value: 1 + }, + { + name: "Dual", + value: 2 + }, + { + name: "Triple", + value: 3 + } + ], + }, + { + name: "UserName", + type: "text", + isArray: false, + }, + { + name: "ExpiringTimeoutMinutes", + type: "number", + isArray: false, + }, + { + name: "UserNameEncoding", + type: "enum", + isArray: false, + enum:[ + { + name: "ASCII", + value: 0 + }, + { + name: "OEMExtendedASCII", + value: 1 + }, + { + name: "UTF-16", + value: 2 + } + ], + } + ] + }, + { + id: 2, + name: "ModifyUser", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "UserType", + type: "enum", + isArray: false, + enum:[ + { + name: "GeneralUser", + value: 0 + }, + { + name: "ProgrammingUser", + value: 3 + }, + { + name: "NonAccessUser", + value: 4 + }, + { + name: "DuressUser", + value: 5 + }, + { + name: "DisposableUser", + value: 6 + }, + { + name: "ExpiringUser", + value: 7 + }, + { + name: "RemoteOnlyUser", + value: 9 + } + ], + }, + { + name: "UserActiveState", + type: "boolean", + isArray: false, + }, + { + name: "CredentialRule", + type: "enum", + isArray: false, + enum:[ + { + name: "Single", + value: 1 + }, + { + name: "Dual", + value: 2 + }, + { + name: "Triple", + value: 3 + } + ], + }, + { + name: "UserName", + type: "text", + isArray: false, + }, + { + name: "ExpiringTimeoutMinutes", + type: "number", + isArray: false, + }, + { + name: "UserNameEncoding", + type: "enum", + isArray: false, + enum:[ + { + name: "ASCII", + value: 0 + }, + { + name: "OEMExtendedASCII", + value: 1 + }, + { + name: "UTF-16", + value: 2 + } + ], + } + ] + }, + { + id: 3, + name: "DeleteUser", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + } + ] + }, + { + id: 4, + name: "AddCredential", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + }, + { + name: "CredentialSlot", + type: "number", + isArray: false, + }, + { + name: "CredentialData", + type: "text", + isArray: false, + } + ] + }, + { + id: 5, + name: "ModifyCredential", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + }, + { + name: "CredentialSlot", + type: "number", + isArray: false, + }, + { + name: "CredentialData", + type: "text", + isArray: false, + } + ] + }, + { + id: 6, + name: "DeleteCredential", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + }, + { + name: "CredentialSlot", + type: "number", + isArray: false, + } + ] + }, + { + id: 7, + name: "DeleteAllUsers", + required: false, + fields: [ + ] + }, + { + id: 8, + name: "DeleteAllCredentials", + required: false, + fields: [ + ] + }, + { + id: 9, + name: "DeleteAllCredentialsByType", + required: false, + fields: [ + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + } + ] + }, + { + id: 10, + name: "DeleteAllCredentialsForUser", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + } + ] + }, + { + id: 11, + name: "DeleteAllCredentialsForUserByType", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + } + ] + }, + { + id: 12, + name: "CredentialLearnStartAdd", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + }, + { + name: "CredentialSlot", + type: "number", + isArray: false, + }, + { + name: "CredentialLearnTimeout", + type: "number", + isArray: false, + } + ] + }, + { + id: 13, + name: "CredentialLearnStartModify", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + }, + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + }, + { + name: "CredentialSlot", + type: "number", + isArray: false, + }, + { + name: "CredentialLearnTimeout", + type: "number", + isArray: false, + } + ] + }, + { + id: 14, + name: "CredentialLearnStop", + required: false, + fields: [ + ] + }, + { + id: 15, + name: "CredentialAssociation", + required: false, + fields: [ + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + }, + { + name: "SourceUserUniqueID", + type: "number", + isArray: false, + }, + { + name: "SourceCredentialSlot", + type: "number", + isArray: false, + }, + { + name: "DestinationUserUniqueID", + type: "number", + isArray: false, + }, + { + name: "DestinationCredentialSlot", + type: "number", + isArray: false, + } + ] + }, + { + id: 16, + name: "GetUserChecksum", + required: false, + fields: [ + { + name: "UserUniqueID", + type: "number", + isArray: false, + } + ] + }, + { + id: 17, + name: "GetCredentialChecksum", + required: false, + fields: [ + { + name: "CredentialType", + type: "enum", + isArray: false, + enum:[ + { + name: "PINCode", + value: 1 + }, + { + name: "Password", + value: 2 + }, + { + name: "RFIDCode", + value: 3 + }, + { + name: "BLE", + value: 4 + }, + { + name: "NFC", + value: 5 + }, + { + name: "UWB", + value: 6 + }, + { + name: "EyeBiometric", + value: 7 + }, + { + name: "FaceBiometric", + value: 8 + }, + { + name: "FingerBiometric", + value: 9 + }, + { + name: "HandBiometric", + value: 10 + }, + { + name: "UnspecifiedBiometric", + value: 11 + } + ], + } + ] + }, + { + id: 18, + name: "GetAllUsersChecksum", + required: false, + fields: [ + ] + }, + { + id: 19, + name: "SetAdminPINCode", + required: false, + fields: [ + { + name: "PINCode", + type: "text", + isArray: false, + } + ] + }, + { + id: 20, + name: "DeactivateAdminPINCode", + required: false, + fields: [ + ] + } + ] + } + }, AoXLocator: { server:{ attributes: [ diff --git a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-types.ts b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-types.ts index 192c0f68f9..07b15f19c3 100644 --- a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-types.ts +++ b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/cluster-types.ts @@ -30,7 +30,8 @@ export enum ClusterTypes { TemperatureMeasurement = "TemperatureMeasurement", Thermostat = "Thermostat", WindSpeedMeasurement = "WindSpeedMeasurement", - WindowCovering = "WindowCovering" + WindowCovering = "WindowCovering", + UserCredential = "UserCredential" } export enum ControllerTypes { diff --git a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/supported-clusters.js b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/supported-clusters.js index 47df47ea30..7dc0c15899 100644 --- a/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/supported-clusters.js +++ b/applications/dev_ui/dev_gui/zap-generated/src/cluster-types/supported-clusters.js @@ -35,7 +35,8 @@ const SupportedClusters = { TemperatureMeasurement: "TemperatureMeasurement", Thermostat: "Thermostat", WindSpeedMeasurement: "WindSpeedMeasurement", - WindowCovering: "WindowCovering" + WindowCovering: "WindowCovering", + UserCredential: "UserCredential" } module.exports.SupportedClusters = SupportedClusters; \ No newline at end of file diff --git a/applications/dev_ui/dev_gui/zap/addon-helper.js b/applications/dev_ui/dev_gui/zap/addon-helper.js index f4460884ba..20887dc0a1 100644 --- a/applications/dev_ui/dev_gui/zap/addon-helper.js +++ b/applications/dev_ui/dev_gui/zap/addon-helper.js @@ -34,7 +34,8 @@ const supportedClusters = [ "TemperatureMeasurement", "Thermostat", "WindSpeedMeasurement", - "WindowCovering" + "WindowCovering", + "UserCredential" ]; let enums = new Set(); diff --git a/applications/zpc/components/dotdot_mapper/rules/UserCredential.uam b/applications/zpc/components/dotdot_mapper/rules/UserCredential.uam new file mode 100644 index 0000000000..40f64380fd --- /dev/null +++ b/applications/zpc/components/dotdot_mapper/rules/UserCredential.uam @@ -0,0 +1,27 @@ +// User Credential CC +def zwUSER_CREDENTIAL_USER_COUNT 0x8302 +def zwUSER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES 0x8303 +def zwUSER_CREDENTIAL_SUPPORTED_USER_TYPES 0x8308 +def zwUSER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM 0x8309 +def zwUSER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE 0x830A +def zwUSER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION 0x830B + +// This represents short CamelCase labels the attributes in the DotDot UserCredential cluster +def zb_SupportedUserUniqueIdentifiers 0xfd080000 +def zb_SupportedCredentialRules 0xfd080001 +// def zb_SupportedCredentialTypes 0xfd080002 Binding is done in user_credential directly +def zb_SupportedUserTypes 0xfd080003 +def zb_SupportCredentialChecksum 0xfd080004 +def zb_SupportAdminPinCode 0xfd080005 +def zb_SupportAdminPinCodeDeactivation 0xfd080006 +// def zb_AdminPinCode 0xfd080007 Binding is done in user_credential_cluster_server directly + +scope 0 chain_reaction(0) { + r'zb_SupportedUserUniqueIdentifiers = r'zwUSER_CREDENTIAL_USER_COUNT + r'zb_SupportedCredentialRules = r'zwUSER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES + r'zb_SupportedUserTypes = r'zwUSER_CREDENTIAL_SUPPORTED_USER_TYPES + + r'zb_SupportCredentialChecksum = r'zwUSER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM + r'zb_SupportAdminPinCode = r'zwUSER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE + r'zb_SupportAdminPinCodeDeactivation = r'zwUSER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION +} \ No newline at end of file diff --git a/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt b/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt index 8827e1f084..bef0569bc4 100644 --- a/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt +++ b/applications/zpc/components/zcl_cluster_servers/CMakeLists.txt @@ -9,6 +9,7 @@ add_library( zcl_cluster_servers src/configuration_parameter_cluster_server.cpp src/humidity_control_cluster_server.c + src/user_credential_cluster_server.cpp src/user_code_cluster_server.cpp src/fan_control_cluster_server.c src/zcl_binding_cluster_server.cpp diff --git a/applications/zpc/components/zcl_cluster_servers/src/configuration_parameter_cluster_server.cpp b/applications/zpc/components/zcl_cluster_servers/src/configuration_parameter_cluster_server.cpp index 5c57bd4039..3f2c928e1c 100644 --- a/applications/zpc/components/zcl_cluster_servers/src/configuration_parameter_cluster_server.cpp +++ b/applications/zpc/components/zcl_cluster_servers/src/configuration_parameter_cluster_server.cpp @@ -521,7 +521,7 @@ static void clear_configuration_parameters_vector(configuration); // Do it again for the Reported value - get_configuration_parameters(endpoint_id_node, + get_configuration_parameters(endpoint_id_node, configuration, REPORTED_ATTRIBUTE); uic_mqtt_dotdot_configuration_parameters_configuration_parameters_publish( diff --git a/applications/zpc/components/zcl_cluster_servers/src/user_credential_cluster_server.cpp b/applications/zpc/components/zcl_cluster_servers/src/user_credential_cluster_server.cpp new file mode 100644 index 0000000000..4afbf6f69e --- /dev/null +++ b/applications/zpc/components/zcl_cluster_servers/src/user_credential_cluster_server.cpp @@ -0,0 +1,1193 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +#include "user_credential_cluster_server.h" +#include "zcl_cluster_servers_helpers.hpp" +// Interfaces +#include "zwave_command_class_user_credential.h" +#include "zwave_command_class_user_credential_api.h" + +// ZPC includes +#include "zpc_attribute_store.h" +#include "zpc_attribute_store_network_helper.h" +#include "zwave_command_class_generic_types.h" +#include "attribute_store_defined_attribute_types.h" +#include "attribute_store_type_registration.h" + +// Includes from Unify shared components +#include "attribute.hpp" +#include "attribute_store_helper.h" +#include "sl_log.h" + +// Includes from auto-generated files +#include "dotdot_mqtt.h" +#include "dotdot_mqtt_helpers.hpp" +#include "zap-types.h" + +// Generic includes +#include +#include +#include +#include + +// JSON +#include + +// Boost +#include +#include + +// UTF16 conversion (deprecated in C++17) +// Needed for credential data (password) per specification +#include +#include + +// Setup Log ID +constexpr char LOG_TAG[] = "user_credential_cluster_server"; + +// Attribute macro, shortening those long defines for attribute types: +#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_##type + +/////////////////////////////////////////////////////////////////////// +// Data structures +/////////////////////////////////////////////////////////////////////// +// Data structure to hold the MQTT topic and conversion function (if needed) for each attribute +struct mqtt_data { + std::string topic; + std::function convert_function = nullptr; +}; +// Used to bind an attribute to a MQTT topic +typedef std::map user_attributes_mqtt_map_t; + +/////////////////////////////////////////////////////////////////////// +// Conversion functions +/////////////////////////////////////////////////////////////////////// +std::string convert_to_bool(uint32_t value) +{ + return value ? "true" : "false"; +} + +/////////////////////////////////////////////////////////////////////// +// Static variables +/////////////////////////////////////////////////////////////////////// +// User attributes +static const user_attributes_mqtt_map_t user_attributes = { + {ATTRIBUTE(USER_TYPE), {"UserType", user_type_enum_get_enum_value_name}}, + {ATTRIBUTE(USER_ACTIVE_STATE), {"UserActiveState", convert_to_bool}}, + {ATTRIBUTE(CREDENTIAL_RULE), + {"CredentialRule", cred_rule_get_enum_value_name}}, + {ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES), {"ExpiringTimeoutMinutes"}}, + {ATTRIBUTE(USER_NAME_ENCODING), + {"UserNameEncoding", user_name_encoding_type_get_enum_value_name}}, + {ATTRIBUTE(USER_MODIFIER_TYPE), + {"UserModifierType", user_modifier_type_get_enum_value_name}}, + {ATTRIBUTE(USER_MODIFIER_NODE_ID), {"UserModifierNodeId"}}, + {ATTRIBUTE(USER_NAME), {"UserName"}}, + {ATTRIBUTE(USER_CHECKSUM), {"UserChecksum"}}, + {ATTRIBUTE(USER_CHECKSUM_MISMATCH_ERROR), {"UserChecksumError"}}, +}; + +// Credential attributes +static const user_attributes_mqtt_map_t credential_attributes + = {{ATTRIBUTE(CREDENTIAL_READ_BACK), {"CredentialReadBack", convert_to_bool}}, + {ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE), + {"CredentialModifierType", user_modifier_type_get_enum_value_name}}, + {ATTRIBUTE(CREDENTIAL_MODIFIER_NODE_ID), {"CredentialModifierNodeId"}}, + {ATTRIBUTE(CREDENTIAL_DATA), {"CredentialData"}}, + {ATTRIBUTE(ASSOCIATION_STATUS), {"AssociationStatus"}}, + {ATTRIBUTE(CREDENTIAL_LEARN_STATUS), {"CredentialLearnStatus"}}}; + +static const user_attributes_mqtt_map_t credential_rules_attributes = { + {ATTRIBUTE(CREDENTIAL_LEARN_SUPPORT), {"LearnSupport", convert_to_bool}}, + {ATTRIBUTE(CREDENTIAL_SUPPORTED_SLOT_COUNT), {"SupportedSlotCount"}}, + {ATTRIBUTE(CREDENTIAL_MIN_LENGTH), {"CredentialMinLength"}}, + {ATTRIBUTE(CREDENTIAL_MAX_LENGTH), {"CredentialMaxLength"}}, + {ATTRIBUTE(CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT), + {"LearnRecommendedTimeout"}}, + {ATTRIBUTE(CREDENTIAL_LEARN_NUMBER_OF_STEPS), {"LearnNumberOfSteps"}}, + {ATTRIBUTE(CREDENTIAL_CHECKSUM), {"CredentialChecksum"}}, + {ATTRIBUTE(CREDENTIAL_CHECKSUM_MISMATCH_ERROR), {"CredentialChecksumError"}}}; + +/////////////////////////////////////////////////////////////////////////////// +// DotDot MQTT incoming commands handling functions +////////////////////////////////////////////////////////////////////////////// +static sl_status_t + add_user_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + UserTypeEnum user_type, + bool user_active_state, + CredRule credential_rule, + const char *user_name, + uint16_t expiring_timeout_minutes, + UserNameEncodingType user_name_encoding) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, USER_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_add_new_user( + endpoint_node, + user_uniqueid, + static_cast(user_type), + static_cast(credential_rule), + user_active_state, + expiring_timeout_minutes, + static_cast(user_name_encoding), + user_name); +} + +static sl_status_t + modify_user_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + UserTypeEnum user_type, + bool user_active_state, + CredRule credential_rule, + const char *user_name, + uint16_t expiring_timeout_minutes, + UserNameEncodingType user_name_encoding) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, USER_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_modify_user( + endpoint_node, + user_uniqueid, + static_cast(user_type), + static_cast(credential_rule), + user_active_state, + expiring_timeout_minutes, + static_cast(user_name_encoding), + user_name); + + return SL_STATUS_OK; +} + +static sl_status_t + delete_user_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, USER_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_user(endpoint_node, + user_uniqueid); +} + +static sl_status_t + add_credential_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + CredType credential_type, + uint16_t credential_slot, + const char *credential_data) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_add_new_credential( + endpoint_node, + user_uniqueid, + static_cast(credential_type), + credential_slot, + credential_data); +} + +static sl_status_t + modify_credential_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + CredType credential_type, + uint16_t credential_slot, + const char *credential_data) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + return zwave_command_class_user_credential_modify_credential( + endpoint_node, + user_uniqueid, + static_cast(credential_type), + credential_slot, + credential_data); +} + +static sl_status_t + delete_credential_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + CredType credential_type, + uint16_t credential_slot) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_credential( + endpoint_node, + user_uniqueid, + static_cast(credential_type), + credential_slot); +} + +static sl_status_t + delete_all_users_command(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, USER_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_all_users(endpoint_node); +} + +static sl_status_t + delete_all_credentials(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_all_credentials( + endpoint_node); +} + +static sl_status_t + delete_all_credentials_by_type(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + CredType credential_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_all_credentials_by_type( + endpoint_node, + static_cast(credential_type)); +} + +static sl_status_t delete_all_credentials_for_user( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_unique_id) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_all_credentials_for_user( + endpoint_node, + user_unique_id); +} + +static sl_status_t delete_all_credentials_for_user_by_type( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_unique_id, + CredType credential_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_delete_all_credentials_for_user_by_type( + endpoint_node, + user_unique_id, + static_cast(credential_type)); +} + +sl_status_t + credential_learn_start_add(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + CredType credential_type, + uint16_t credential_slot, + uint8_t credential_learn_timeout) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_LEARN_START) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_credential_learn_start_add( + endpoint_node, + user_uniqueid, + static_cast(credential_type), + credential_slot, + credential_learn_timeout); +} + +sl_status_t + credential_learn_start_modify(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + CredType credential_type, + uint16_t credential_slot, + uint8_t credential_learn_timeout) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_LEARN_START) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_credential_learn_start_modify( + endpoint_node, + user_uniqueid, + static_cast(credential_type), + credential_slot, + credential_learn_timeout); +} + +sl_status_t + credential_learn_stop(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_LEARN_CANCEL) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_credential_learn_stop( + endpoint_node); +} + +sl_status_t uuic_association_set(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + CredType credential_type, + uint16_t source_user_uniqueid, + uint16_t source_credential_slot, + uint16_t destination_user_uniqueid, + uint16_t destination_credential_slot) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports( + endpoint_node, + USER_CREDENTIAL_ASSOCIATION_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_uuic_association_set( + endpoint_node, + static_cast(credential_type), + source_user_uniqueid, + source_credential_slot, + destination_user_uniqueid, + destination_credential_slot); +} + +sl_status_t + get_all_users_checksum(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + ALL_USERS_CHECKSUM_GET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_get_all_users_checksum( + endpoint_node); +} + +sl_status_t get_user_checksum(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + USER_CHECKSUM_GET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_get_user_checksum(endpoint_node, + user_uniqueid); +} + +sl_status_t + get_credential_checksum(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + CredType credential_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + CREDENTIAL_CHECKSUM_GET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_get_credential_checksum( + endpoint_node, + credential_type); +} + +sl_status_t admin_pin_code_set(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + const char *credential_data) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return zwave_command_class_user_credential_supports(endpoint_node, + ADMIN_PIN_CODE_SET) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_set_admin_pin_code( + endpoint_node, + credential_data); +} + +sl_status_t + admin_pin_code_deactivate(dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type) +{ + attribute_store_node_t endpoint_node + = attribute_store_network_helper_get_endpoint_node(unid, endpoint); + + // Now that we know that the command is supported, return here if it is + // a support check type of call. + if (UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK == call_type) { + return (zwave_command_class_user_credential_supports(endpoint_node, + ADMIN_PIN_CODE_SET) + && zwave_command_class_user_credential_supports_admin_pin_code_deactivation( + endpoint_node)) + ? SL_STATUS_OK + : SL_STATUS_FAIL; + } + + return zwave_command_class_user_credential_set_admin_pin_code(endpoint_node, + ""); +}; + +/////////////////////////////////////////////////////////////////////////////// +// Helpers functions +////////////////////////////////////////////////////////////////////////////// +void register_attributes_to_mqtt_map( + const user_attributes_mqtt_map_t &map, + attribute_store_node_changed_callback_t callback) +{ + sl_status_t status = SL_STATUS_OK; + for (const auto &[attribute_store_type, mqtt_data]: map) { + status |= attribute_store_register_callback_by_type_and_state( + callback, + attribute_store_type, + REPORTED_ATTRIBUTE); + } + if (status != SL_STATUS_OK) { + sl_log_error(LOG_TAG, "Failed to register callbacks for User Credential"); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// Callbacks +////////////////////////////////////////////////////////////////////////////// +void on_admin_pin_code_update(attribute_store_node_t updated_node, + attribute_store_change_t change) +{ + if (change != ATTRIBUTE_UPDATED) { + return; + } + + attribute_store::attribute admin_pin_code_node(updated_node); + if (!admin_pin_code_node.reported_exists()) { + return; + } + + auto raw_pin_code = admin_pin_code_node.reported>(); + std::string pin_code_str(raw_pin_code.begin(), raw_pin_code.end()); + + try { + admin_pin_code_node.first_parent(ATTRIBUTE_ENDPOINT_ID) + .emplace_node(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE) + .set_reported(pin_code_str); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while updating ZLC Admin Pin Code attribute : %s", + e.what()); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// MQTT Helpers functions +////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Get the base MQTT topic for a UserCredential. + * + * This function will return the base MQTT topic for a UserCredential based on the + * updated node. The topic will be in the format: + * ucl/by-unid//ep/UserCredential/Attributes +*/ +std::string get_base_mqtt_topic(attribute_store::attribute updated_node_cpp) +{ + boost::format mqtt_topic + = boost::format("ucl/by-unid/%1%/ep%2%/UserCredential/Attributes"); + + // Go up and find the UNID/Endpoint and its network status. + unid_t unid; + zwave_endpoint_id_t endpoint_id = 0; + if (SL_STATUS_OK + != attribute_store_network_helper_get_unid_endpoint_from_node( + updated_node_cpp, + unid, + &endpoint_id)) { + return ""; + } + + // Do not publish any state supported commands for ourselves. + if (is_zpc_unid(unid)) { + return ""; + } + + // Need to convert endpoint_id to an unsigned int to be displayed as an int and not a char + return (mqtt_topic % unid % static_cast(endpoint_id)).str(); +} + +/** + * @brief Get the base MQTT topic for a user. + * + * @see get_base_user_mqtt_topic(attribute_store::attribute) + */ +std::string + get_base_user_mqtt_topic_str(const std::string &base_mqtt_topic, + user_credential_user_unique_id_t user_id) +{ + return (boost::format("%1%/User/%2%") % base_mqtt_topic % user_id).str(); +} + +/** + * @brief Get the base MQTT topic for a user. + * + * This function will return the base MQTT topic for a user based on the + * updated node. The topic will be in the format: + * ucl/by-unid//ep/UserCredential/Attributes/User/ + * + * @param updated_node_cpp The node that will be published. + * @return The base MQTT topic for the user. + */ +std::string + get_base_user_mqtt_topic(attribute_store::attribute updated_node_cpp) +{ + boost::format mqtt_topic = boost::format("%1%/User/%2%"); + + std::string base_mqtt_topic = get_base_mqtt_topic(updated_node_cpp); + if (base_mqtt_topic.empty()) { + return ""; + } + + try { + user_credential_user_unique_id_t user_id + = updated_node_cpp.first_parent_or_self(ATTRIBUTE(USER_UNIQUE_ID)) + .reported(); + + return get_base_user_mqtt_topic_str(base_mqtt_topic, user_id); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while publishing User attribute (%s) : %s", + attribute_store_type_get_node_type_name(updated_node_cpp), + e.what()); + } + + return ""; +} + +/** + * @brief Get the base MQTT topic for a credential. + * + * @see get_base_credential_mqtt_topic(attribute_store::attribute updated_node_cpp) + */ +std::string + get_base_credential_mqtt_topic_str(const std::string &base_user_mqtt_topic, + user_credential_slot_t credential_slot, + user_credential_type_t credential_type) +{ + std::string credential_type_str + = cred_type_get_enum_value_name(credential_type); + return (boost::format("%1%/Credential/%2%/%3%") % base_user_mqtt_topic + % credential_type_str % credential_slot) + .str(); +} + +/** + * @brief Get the base MQTT topic for a credential. + * + * This function will return the base MQTT topic for a credential based on the + * updated node. The topic will be in the format: + * ucl/by-unid//ep/UserCredential/Attributes/User//Credential////Reported + * + * @param updated_node_cpp The updated node. + * @return The base MQTT topic for the credential. + */ +std::string + get_base_credential_mqtt_topic(attribute_store::attribute updated_node_cpp) +{ + std::string base_user_mqtt_topic = get_base_user_mqtt_topic(updated_node_cpp); + if (base_user_mqtt_topic.empty()) { + return ""; + } + + try { + user_credential_slot_t credential_slot + = updated_node_cpp.first_parent(ATTRIBUTE(CREDENTIAL_SLOT)) + .reported(); + + user_credential_type_t credential_type + = updated_node_cpp.first_parent(ATTRIBUTE(CREDENTIAL_TYPE)) + .reported(); + + return get_base_credential_mqtt_topic_str(base_user_mqtt_topic, + credential_slot, + credential_type); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while publishing Credential attribute (%s) : %s", + attribute_store_type_get_node_type_name(updated_node_cpp), + e.what()); + } + + return ""; +} + +std::string get_base_credential_rule_mqtt_topic( + attribute_store::attribute updated_node_cpp) +{ + std::string base_user_mqtt_topic = get_base_mqtt_topic(updated_node_cpp); + if (base_user_mqtt_topic.empty()) { + return ""; + } + + try { + user_credential_type_t credential_type + = updated_node_cpp.first_parent(ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE)) + .reported(); + std::string credential_type_str + = cred_type_get_enum_value_name(credential_type); + + return (boost::format("%1%/Credentials/%2%") % base_user_mqtt_topic + % credential_type_str) + .str(); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while publishing Credential Rule attribute (%s) : %s", + attribute_store_type_get_node_type_name(updated_node_cpp), + e.what()); + } + + return ""; +} + +/** + * @brief Add an attribute to the MQTT topic. + * + * This function will add an attribute to the MQTT topic. The topic will be in + * the format: + * //Reported + * + * @param base_mqtt_topic The base MQTT topic. + * @param attribute_name The attribute name to add. + * @return The full MQTT topic. + */ +std::string mqtt_topic_add_attribute(const std::string &base_mqtt_topic, + const std::string &attribute_name) +{ + return (boost::format("%1%/%2%/Reported") % base_mqtt_topic % attribute_name) + .str(); +} + +/** + * @brief Get the payload value for the attribute. + * + * This function will get the payload value for the attribute. The payload will + * be in the format: + * { + * "value": + * } + * + * @param updated_node_cpp The updated node. + * @param data The MQTT data. + * @param need_utf8_conversion If the value needs to be converted to UTF-8. Only applies to C_STRING_STORAGE_TYPE. + * + * @return The payload value. + */ +std::string get_payload_value(attribute_store::attribute updated_node_cpp, + mqtt_data data, + bool need_utf8_conversion = false) +{ + std::string payload_str = ""; + + auto node_storage_type + = attribute_store_get_storage_type(updated_node_cpp.type()); + nlohmann::json json_payload; + switch (node_storage_type) { + case U8_STORAGE_TYPE: + json_payload["value"] = updated_node_cpp.reported(); + break; + case U16_STORAGE_TYPE: + json_payload["value"] = updated_node_cpp.reported(); + break; + case U32_STORAGE_TYPE: + json_payload["value"] = updated_node_cpp.reported(); + break; + case C_STRING_STORAGE_TYPE: + json_payload["value"] = updated_node_cpp.reported(); + break; + case BYTE_ARRAY_STORAGE_TYPE: { + // Convert the byte array to a string + // Credential data are encoded in different way that's why we store them as raw byte array and interpret their value + + std::string output; + auto raw_data = updated_node_cpp.reported>(); + + // Check if we need to convert the value to UTF-8 + if (need_utf8_conversion) { + std::u16string utf16_str; + for (size_t i = 0; i < raw_data.size(); i += 2) { + char16_t char16 = (raw_data[i] << 8) | raw_data[i + 1]; + utf16_str.push_back(char16); + } + std::wstring_convert, char16_t> cnv; + output = cnv.to_bytes(utf16_str); + if (cnv.converted() < utf16_str.size()) { + sl_log_error(LOG_TAG, "Error converting UTF-16 to UTF-8"); + } + } else { + output.reserve(raw_data.size()); + for (auto c: raw_data) { + output.push_back(static_cast(c)); + } + } + + json_payload["value"] = output; + } break; + + default: + sl_log_error(LOG_TAG, + "Unsupported storage type for user credential attribute"); + return ""; + } + + // Check if we need to convert the enum to a string + const auto &enum_name_conversion = data.convert_function; + if (enum_name_conversion) { + json_payload["value"] = enum_name_conversion(json_payload["value"]); + } + + // Create payload + payload_str = json_payload.dump(); + // Handle booleans + if (enum_name_conversion) { + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); + } + + return payload_str; +} + +void publish_mqtt_topic(const std::string &base_topic, + mqtt_data data, + attribute_store::attribute updated_node_cpp, + attribute_store_change_t change) +{ + std::string mqtt_topic = mqtt_topic_add_attribute(base_topic, data.topic); + sl_log_debug(LOG_TAG, "Publishing to topic: %s", mqtt_topic.c_str()); + + std::string payload_str = ""; + if (change != ATTRIBUTE_DELETED) { + if (updated_node_cpp.type() == ATTRIBUTE(CREDENTIAL_DATA)) { + // Credential data are encoded in different way that's why we store them as raw byte array and interpret their value + // We need to convert the value to UTF-8 if the credential type is password + user_credential_type_t type + = updated_node_cpp.first_parent(ATTRIBUTE(CREDENTIAL_TYPE)) + .reported(); + payload_str = get_payload_value(updated_node_cpp, + data, + (type == ZCL_CRED_TYPE_PASSWORD)); + } else { + payload_str = get_payload_value(updated_node_cpp, data); + } + if (payload_str.empty()) { + return; + } + sl_log_debug(LOG_TAG, "Payload %s", payload_str.c_str()); + } else { + sl_log_debug(LOG_TAG, "Deletion of attribute, sending empty payload"); + } + + // Publish topic + uic_mqtt_publish(mqtt_topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); +} + +/////////////////////////////////////////////////////////////////////////////// +// Attribute monitoring +////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Callback for when an attribute is updated. + * + * This function will be called when an attribute is updated. It will then + * publish the updated attribute to the MQTT broker. + * + * @param updated_node The updated node. + * @param change The change that occurred. + * @param get_base_mqtt_topic The function to get the base MQTT topic. + * @param attributes The attributes data to publish. +*/ +void on_attribute_update( + attribute_store_node_t updated_node, + attribute_store_change_t change, + const std::function& get_base_mqtt_topic, + const user_attributes_mqtt_map_t &attributes) +{ + try { + auto updated_node_cpp = attribute_store::attribute(updated_node); + // If no reported value exists, we wait for it + if (!updated_node_cpp.reported_exists()) { + return; + } + + // Build the base topic and pass it on to DotDot MQTT. + std::string mqtt_topic = get_base_mqtt_topic(updated_node_cpp); + if (mqtt_topic.empty()) { + return; + } + + const auto mqtt_data = attributes.at(updated_node_cpp.type()); + + publish_mqtt_topic(mqtt_topic, mqtt_data, updated_node_cpp, change); + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while publishing User Credential attribute: %s", + e.what()); + } +} + +void on_user_update(attribute_store_node_t updated_node, + attribute_store_change_t change) +{ + on_attribute_update(updated_node, + change, + &get_base_user_mqtt_topic, + user_attributes); +} + +void on_credential_rules_update(attribute_store_node_t updated_node, + attribute_store_change_t change) +{ + on_attribute_update(updated_node, + change, + &get_base_credential_rule_mqtt_topic, + credential_rules_attributes); +} + +void on_credential_update(attribute_store_node_t updated_node, + attribute_store_change_t change) +{ + on_attribute_update(updated_node, + change, + &get_base_credential_mqtt_topic, + credential_attributes); +} + +/** + * @brief Callback for when a UUIC slot is updated. + * + * This is used to update the MQTT topics when a slot is updated. + * Since we only monitor properties of the slot, we need to update the slot + * itself when it changes. + * + * This callback is called whenever a slot is updated thanks to the UUIC command. + * + * @param old_credential_slot The old credential slot id. + * @param node The node that contains the updated slot. + */ +void on_uuic_slot_update( + const user_credential_credential_identifier_t old_credential_slot, + attribute_store_node_t node) +{ + auto credential_slot_node = attribute_store::attribute(node); + + // Update old slot + auto old_user_topic + = get_base_user_mqtt_topic_str(get_base_mqtt_topic(credential_slot_node), + old_credential_slot.user_unique_id); + auto old_credential_topic + = get_base_credential_mqtt_topic_str(old_user_topic, + old_credential_slot.credential_slot, + old_credential_slot.credential_type); + // Simulate deletion of the old slot + // First simulate deletion of all attributes + for (const auto& [attribute_store_type, mqtt_data]: credential_attributes) { + std::string mqtt_topic + = mqtt_topic_add_attribute(old_credential_topic, mqtt_data.topic); + uic_mqtt_publish(mqtt_topic.c_str(), "", 0, true); + } + // Then delete the slot itself + uic_mqtt_publish(old_credential_topic.c_str(), "", 0, true); + + // Trigger update for the new slot + for (auto child: credential_slot_node.children()) { + on_credential_update(child, ATTRIBUTE_UPDATED); + } +} + +void on_user_credential_message(sl_log_level_t log_level, + const std::string& message) +{ + nlohmann::json payload; + payload["level"] = log_level; + payload["message"] = message; + + std::string payload_str = payload.dump(); + uic_mqtt_publish("ucl/Event", + payload_str.c_str(), + payload_str.length(), + true); +} + +/////////////////////////////////////////////////////////////////////////////// +// Init and teardown functions. +////////////////////////////////////////////////////////////////////////////// +sl_status_t user_credential_cluster_server_init() +{ + sl_log_debug(LOG_TAG, "User Credential server initialization"); + + // User properties update + register_attributes_to_mqtt_map(user_attributes, &on_user_update); + register_attributes_to_mqtt_map(credential_attributes, &on_credential_update); + register_attributes_to_mqtt_map(credential_rules_attributes, + &on_credential_rules_update); + + // Custom callbacks + zwave_command_class_user_credential_set_uuic_slot_changed_callback( + &on_uuic_slot_update); + zwave_command_class_user_credential_set_message_callback( + &on_user_credential_message); + + // Command callbacks + // User + uic_mqtt_dotdot_user_credential_add_user_callback_set(&add_user_command); + uic_mqtt_dotdot_user_credential_modify_user_callback_set( + &modify_user_command); + uic_mqtt_dotdot_user_credential_delete_user_callback_set( + &delete_user_command); + // Credential + uic_mqtt_dotdot_user_credential_add_credential_callback_set( + &add_credential_command); + uic_mqtt_dotdot_user_credential_modify_credential_callback_set( + &modify_credential_command); + uic_mqtt_dotdot_user_credential_delete_credential_callback_set( + &delete_credential_command); + // Delete all + uic_mqtt_dotdot_user_credential_delete_all_users_callback_set( + &delete_all_users_command); + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set( + &delete_all_credentials); + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set( + &delete_all_credentials_by_type); + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set( + &delete_all_credentials_for_user); + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set( + &delete_all_credentials_for_user_by_type); + // Credential Learn + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set( + &credential_learn_start_add); + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set( + &credential_learn_start_modify); + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set( + &credential_learn_stop); + // UUIC association + uic_mqtt_dotdot_user_credential_credential_association_callback_set( + &uuic_association_set); + // User Checksum + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set( + &get_user_checksum); + // Credential Checksum + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set( + &get_credential_checksum); + // All Users Checksum + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set( + &get_all_users_checksum); + // Admin PIN code + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set( + &admin_pin_code_set); + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set( + &admin_pin_code_deactivate); + + // Types that can't be mapped with UAM + attribute_store_register_callback_by_type_and_state(&on_admin_pin_code_update, + ATTRIBUTE(ADMIN_PIN_CODE), + REPORTED_ATTRIBUTE); + + return SL_STATUS_OK; +} diff --git a/applications/zpc/components/zcl_cluster_servers/src/user_credential_cluster_server.h b/applications/zpc/components/zcl_cluster_servers/src/user_credential_cluster_server.h new file mode 100644 index 0000000000..0315fb45a2 --- /dev/null +++ b/applications/zpc/components/zcl_cluster_servers/src/user_credential_cluster_server.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +/** + * @defgroup user_credential_cluster_server User Code Cluster Server + * @ingroup zcl_cluster_servers + * @brief The module handlers the User Code command mapping + * @{ + */ + +#ifndef USER_CREDENTIAL_CLUSTER_SERVER_H +#define USER_CREDENTIAL_CLUSTER_SERVER_H + +#include "sl_status.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the User Code Cluster Commands handler. + * + * @returns SL_STATUS_OK on success, any other code on failure + */ +sl_status_t user_credential_cluster_server_init(); + +#ifdef __cplusplus +} +#endif + +#endif //USER_CREDENTIAL_CLUSTER_SERVER_H +/** @} end user_credential_cluster_server */ diff --git a/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp b/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp index 7c959d555b..43bc4c3854 100644 --- a/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp +++ b/applications/zpc/components/zcl_cluster_servers/src/zcl_cluster_servers.cpp @@ -19,6 +19,7 @@ #include "zcl_OTA_cluster_server.hpp" #include "user_code_cluster_server.h" #include "fan_control_cluster_server.h" +#include "user_credential_cluster_server.h" //Includes from other components #include "attribute_store.h" @@ -42,6 +43,7 @@ sl_status_t zcl_cluster_servers_init() init_status |= zcl_scenes_cluster_server_init(); init_status |= user_code_cluster_server_init(); init_status |= fan_control_cluster_server_init(); + init_status |= user_credential_cluster_server_init(); return init_status; } diff --git a/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt b/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt index a5142592a1..6112d25e83 100644 --- a/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt +++ b/applications/zpc/components/zcl_cluster_servers/test/CMakeLists.txt @@ -126,4 +126,20 @@ target_add_unittest( DEPENDS zpc_attribute_store_test_helper uic_dotdot_mqtt_mock - unify_dotdot_attribute_store) \ No newline at end of file + unify_dotdot_attribute_store) + + + # User Credential Cluster Server test +target_add_unittest( + zcl_cluster_servers + NAME + user_credential_cluster_server_test + SOURCES + user_credential_cluster_server_test.cpp + DEPENDS + zpc_attribute_store_test_helper + uic_dotdot_mqtt_mock + uic_mqtt_stub + uic_attribute_store + unify) +target_include_directories(user_credential_cluster_server_test PRIVATE ../src) \ No newline at end of file diff --git a/applications/zpc/components/zcl_cluster_servers/test/user_credential_cluster_server_test.cpp b/applications/zpc/components/zcl_cluster_servers/test/user_credential_cluster_server_test.cpp new file mode 100644 index 0000000000..f9e8d1e1f0 --- /dev/null +++ b/applications/zpc/components/zcl_cluster_servers/test/user_credential_cluster_server_test.cpp @@ -0,0 +1,2654 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +// Cpp +#include +#include "workaround_for_test.hpp" +#include "attribute.hpp" + +extern "C" { +#include "user_credential_cluster_server.h" +#include "zwave_command_class_user_credential.h" +#include "unity.h" + +// Definitions +#include "dotdot_cluster_id_definitions.h" +#include "attribute_store_defined_attribute_types.h" +#include "zwave_command_class_association_types.h" +#include "zap-types.h" +#include "zwave_command_class_version_types.h" + +// ZPC Components +#include "zpc_attribute_store_type_registration.h" + +// Test helpers +#include "zpc_attribute_store_test_helper.h" +#include "sl_log.h" + +// Unify components +#include "datastore.h" +#include "attribute_store.h" +#include "attribute_store_helper.h" +#include "attribute_store_fixt.h" +#include "unify_dotdot_attribute_store_node_state.h" + +// Mocks +#include "dotdot_mqtt_mock.h" +#include "uic_mqtt_mock.h" + +// Attribute macro, shortening those long defines for attribute types: +#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_##type + +// Useful definitions +attribute_store::attribute cpp_endpoint_node; + +// Header declarations +void mock_deletion_user_mqtt_topic(user_credential_user_unique_id_t user_id); +void mock_deletion_cred_mqtt_topic(user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot); +void mock_deletion_cred_rule_mqtt_topic(user_credential_type_t credential_type); +void setup_user_capabilities(); +void setup_cred_capabilities(); + +// Keep a reference to the mqtt topics we want to test +// Stored as +static std::vector> mqtt_topics; +static std::vector created_user_id; +static std::vector> + created_credential_ids; +static std::vector created_supported_credential_types; + +// Callback functions +// clang-format off +uic_mqtt_dotdot_user_credential_add_user_callback_t add_user_command = NULL; +uic_mqtt_dotdot_user_credential_delete_user_callback_t delete_user_command = NULL; +uic_mqtt_dotdot_user_credential_modify_user_callback_t modify_user_command = NULL; +uic_mqtt_dotdot_user_credential_add_credential_callback_t add_credential_command = NULL; +uic_mqtt_dotdot_user_credential_modify_credential_callback_t modify_credential_command = NULL; +uic_mqtt_dotdot_user_credential_delete_credential_callback_t delete_credential_command = NULL; +uic_mqtt_dotdot_user_credential_delete_all_users_callback_t delete_all_users_command = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t delete_all_credentials_command = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t delete_all_credentials_by_type_command = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t delete_all_credentials_for_user_command = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t delete_all_credentials_for_user_by_type_command = NULL; +uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t credential_learn_start_add_command = NULL; +uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t credential_learn_start_modify_command = NULL; +uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t credential_learn_stop_command = NULL; +uic_mqtt_dotdot_user_credential_credential_association_callback_t credential_association_command = NULL; +uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t get_user_checksum_command = NULL; +uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t get_credential_checksum_command = NULL; +uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t get_all_users_checksum_command = NULL; +uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t set_admin_pin_code_command = NULL; +uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t deactivate_admin_pin_code_command = NULL; +// clang-format on + +// Stub functions for intercepting callback registration. +void uic_mqtt_dotdot_user_credential_add_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_add_user_callback_t callback, + int cmock_num_calls) +{ + add_user_command = callback; +} + +void uic_mqtt_dotdot_user_credential_delete_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback, + int cmock_num_calls) +{ + delete_user_command = callback; +} + +void uic_mqtt_dotdot_user_credential_modify_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback, + int cmock_num_calls) +{ + modify_user_command = callback; +} + +void uic_mqtt_dotdot_user_credential_add_credential_callback_set_stub( + const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback, + int cmock_num_calls) +{ + add_credential_command = callback; +} +void uic_mqtt_dotdot_user_credential_modify_credential_callback_set_stub( + const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback, + int cmock_num_calls) +{ + modify_credential_command = callback; +} +void uic_mqtt_dotdot_user_credential_delete_credential_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback, + int cmock_num_calls) +{ + delete_credential_command = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback, + int cmock_num_calls) +{ + delete_all_users_command = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t + callback, + int cmock_num_calls) +{ + delete_all_credentials_command = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t + callback, + int cmock_num_calls) +{ + delete_all_credentials_by_type_command = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t + callback, + int cmock_num_calls) +{ + delete_all_credentials_for_user_command = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t + callback, + int cmock_num_calls) +{ + delete_all_credentials_for_user_by_type_command = callback; +} + +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t + callback, + int cmock_num_calls) +{ + credential_learn_start_add_command = callback; +} + +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t + callback, + int cmock_num_calls) +{ + credential_learn_start_modify_command = callback; +} + +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t + callback, + int cmock_num_calls) +{ + credential_learn_stop_command = callback; +} + +void uic_mqtt_dotdot_user_credential_credential_association_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_association_callback_t + callback, + int cmock_num_calls) +{ + credential_association_command = callback; +} + +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set_stub( + const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback, + int cmock_num_calls) +{ + get_user_checksum_command = callback; +} + +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set_stub( + const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t + callback, + int cmock_num_calls) +{ + get_credential_checksum_command = callback; +} + +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set_stub( + const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t + callback, + int cmock_num_calls) +{ + get_all_users_checksum_command = callback; +} + +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set_stub( + const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback, + int cmock_num_calls) +{ + set_admin_pin_code_command = callback; +} + +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set_stub( + const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t + callback, + int cmock_num_calls) +{ + deactivate_admin_pin_code_command = callback; +} + +/// Setup the test suite (called once before all test_xxx functions are called) +void suiteSetUp() +{ + datastore_init(":memory:"); + attribute_store_init(); + zpc_attribute_store_register_known_attribute_types(); + zwave_unid_set_home_id(home_id); +} + +/// Teardown the test suite (called once after all test_xxx functions are called) +int suiteTearDown(int num_failures) +{ + attribute_store_teardown(); + datastore_teardown(); + return num_failures; +} + +/// Called before each and every test +void setUp() +{ + sl_log_set_level(sl_log_level::SL_LOG_INFO); + + // If you can to enable MQTT topics logs : + // sl_log_set_tag_level("user_credential_cluster_server", + // sl_log_level::SL_LOG_DEBUG); + + sl_log_set_tag_level("zwave_command_class_user_credential", + sl_log_level::SL_LOG_DEBUG); + sl_log_set_tag_level("attribute_store", sl_log_level::SL_LOG_DEBUG); + + // WARNING : Order matters here + // Check if credential rules need to be removed + for (auto cred_type: created_supported_credential_types) { + mock_deletion_cred_rule_mqtt_topic(cred_type); + } + // Check if any users that need to be removed + for (auto user_id: created_user_id) { + // Check if MQTT topics for deletion are correctly published + mock_deletion_user_mqtt_topic(user_id); + } + for (auto cred_id: created_credential_ids) { + mock_deletion_cred_mqtt_topic(std::get<0>(cred_id), + std::get<1>(cred_id), + std::get<2>(cred_id)); + } + + zpc_attribute_store_test_helper_create_network(); + + // Intercept the dotdot MQTT callbacks + add_user_command = NULL; + modify_user_command = NULL; + delete_user_command = NULL; + add_credential_command = NULL; + + mqtt_topics.clear(); + created_user_id.clear(); + created_credential_ids.clear(); + created_supported_credential_types.clear(); + // clang-format off + // User + uic_mqtt_dotdot_user_credential_add_user_callback_set_Stub(&uic_mqtt_dotdot_user_credential_add_user_callback_set_stub); + uic_mqtt_dotdot_user_credential_delete_user_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_user_callback_set_stub); + uic_mqtt_dotdot_user_credential_modify_user_callback_set_Stub(&uic_mqtt_dotdot_user_credential_modify_user_callback_set_stub); + // Credentials + uic_mqtt_dotdot_user_credential_add_credential_callback_set_Stub(&uic_mqtt_dotdot_user_credential_add_credential_callback_set_stub); + uic_mqtt_dotdot_user_credential_modify_credential_callback_set_Stub(&uic_mqtt_dotdot_user_credential_modify_credential_callback_set_stub); + uic_mqtt_dotdot_user_credential_delete_credential_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_credential_callback_set_stub); + // Delete all + uic_mqtt_dotdot_user_credential_delete_all_users_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_all_users_callback_set_stub); + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set_stub); + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set_stub); + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set_stub); + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set_Stub(&uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set_stub); + // Credential learn + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set_Stub(&uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set_stub); + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set_Stub(&uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set_stub); + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set_Stub(&uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set_stub); + // UUIC association + uic_mqtt_dotdot_user_credential_credential_association_callback_set_Stub(&uic_mqtt_dotdot_user_credential_credential_association_callback_set_stub); + // User checksum + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set_Stub(&uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set_stub); + // Credential checksum + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set_Stub(&uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set_stub); + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set_Stub(&uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set_stub); + // Admin code + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set_Stub(&uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set_stub); + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set_Stub(&uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set_stub); + // clang-format on + + // Run the component init + TEST_ASSERT_EQUAL(SL_STATUS_OK, user_credential_cluster_server_init()); + + // We are not here to test user capabilities, so we need to set them up to + // accept our test data + setup_user_capabilities(); + // Need to call this after init() to have the mqtt callback initialized + setup_cred_capabilities(); + + // Setup helper + cpp_endpoint_node = attribute_store::attribute(endpoint_id_node); + + // Setup global cred capabilities + cpp_endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE), + static_cast(1)); + cpp_endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM), + static_cast(1)); + cpp_endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE_DEACTIVATION), + static_cast(1)); + + // Set command class version + cpp_endpoint_node.emplace_node(ATTRIBUTE(VERSION)).set_reported(1); +} + + + +///////////////////////////////////////////////////////////////////////// +// Mqtt topics helpers +///////////////////////////////////////////////////////////////////////// +std::string get_base_topic(bool include_user = true) +{ + const std::string user_str = include_user ? "/User" : ""; + const std::string base = "ucl/by-unid/%1%/ep%2%/UserCredential/Attributes%3%"; + return (boost::format(base) % supporting_node_unid % (unsigned int)endpoint_id + % user_str) + .str(); +} + +std::string + get_user_attribute_mqtt_topic(user_credential_user_unique_id_t user_unique_id, + const std::string &attribute_name) +{ + const std::string base = "%1%/%2%/%3%/Reported"; + return (boost::format(base) % get_base_topic() % user_unique_id + % attribute_name) + .str(); +} + +std::string + get_cred_attribute_mqtt_topic(user_credential_user_unique_id_t user_unique_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const std::string &attribute_name) +{ + const std::string base = "%1%/%2%/Credential/%3%/%4%/%5%/Reported"; + return (boost::format(base) % get_base_topic() % user_unique_id + % cred_type_get_enum_value_name(credential_type) % credential_slot + % attribute_name) + .str(); +} + +std::string get_cred_rule_mqtt_topic(user_credential_type_t credential_type, + const std::string &attribute_name) +{ + const std::string base = "%1%/Credentials/%2%/%3%/Reported"; + return (boost::format(base) % get_base_topic(false) + % cred_type_get_enum_value_name(credential_type) % attribute_name) + .str(); +} + +} // extern "C" + +template std::string get_payload(T value) +{ + nlohmann::json json_payload; + json_payload["value"] = value; + return json_payload.dump(); +} + +///////////////////////////////////////////////////////////////////////// +// MOCK HELPERS +///////////////////////////////////////////////////////////////////////// +template +void mock_expected_user_mqtt_topic(user_credential_user_unique_id_t user_id, + const std::string &attribute_name, + T payload_value) +{ + // This way we make sure that we have valid reference to our strings + mqtt_topics.push_back({get_user_attribute_mqtt_topic(user_id, attribute_name), + get_payload(payload_value)}); + + uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(), + mqtt_topics.back().second.c_str(), + mqtt_topics.back().second.size(), + true); +} +template +void mock_expected_cred_mqtt_topic(user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const std::string &attribute_name, + T payload_value) +{ + // This way we make sure that we have valid reference to our strings + mqtt_topics.push_back({get_cred_attribute_mqtt_topic(user_id, + credential_type, + credential_slot, + attribute_name), + get_payload(payload_value)}); + + uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(), + mqtt_topics.back().second.c_str(), + mqtt_topics.back().second.size(), + true); +} +template +void mock_expected_cred_rule_mqtt_topic(user_credential_type_t credential_type, + const std::string &attribute_name, + T payload_value) +{ + // This way we make sure that we have valid reference to our strings + mqtt_topics.push_back( + {get_cred_rule_mqtt_topic(credential_type, attribute_name), + get_payload(payload_value)}); + + uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(), + mqtt_topics.back().second.c_str(), + mqtt_topics.back().second.size(), + true); +} +void mock_deletion_user_mqtt_topic(user_credential_user_unique_id_t user_id) +{ + // WARNING : Order here matters based on their initialization order in the add_complete_user function + std::vector attribute_names = {"UserType", + "CredentialRule", + "UserActiveState", + "ExpiringTimeoutMinutes", + "UserNameEncoding", + "UserName", + "UserModifierNodeId", + "UserModifierType", + "UserChecksum", + "UserChecksumError"}; + for (auto &attribute_name: attribute_names) { + mqtt_topics.push_back( + {get_user_attribute_mqtt_topic(user_id, attribute_name), ""}); + uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(), + mqtt_topics.back().second.c_str(), + mqtt_topics.back().second.size(), + true); + } +} + +void mock_deletion_cred_mqtt_topic(user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot) +{ + // WARNING : Order here matters based on their initialization order in the add_complete_credential function + std::vector attribute_names = {"CredentialData", + "AssociationStatus", + "CredentialLearnStatus", + "CredentialModifierNodeId", + "CredentialModifierType"}; + for (auto &attribute_name: attribute_names) { + mqtt_topics.push_back({get_cred_attribute_mqtt_topic(user_id, + credential_type, + credential_slot, + attribute_name), + ""}); + uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(), + mqtt_topics.back().second.c_str(), + mqtt_topics.back().second.size(), + true); + } +} + +void mock_deletion_cred_rule_mqtt_topic(user_credential_type_t credential_type) +{ + // WARNING : Order here matters based on their initialization order in the add_complete_credential function + std::vector attribute_names = {"LearnSupport", + "SupportedSlotCount", + "CredentialMinLength", + "CredentialMaxLength", + "LearnRecommendedTimeout", + "LearnNumberOfSteps"}; + for (auto &attribute_name: attribute_names) { + mqtt_topics.push_back( + {get_cred_rule_mqtt_topic(credential_type, attribute_name), ""}); + uic_mqtt_publish_Expect(mqtt_topics.back().first.c_str(), + mqtt_topics.back().second.c_str(), + mqtt_topics.back().second.size(), + true); + } +} +///////////////////////////////////////////////////////////////////////// +// Capabilities Helper +///////////////////////////////////////////////////////////////////////// +void setup_user_capabilities() +{ + uint16_t number_of_users = 12; + user_credential_supported_credential_rules_t cred_rule_bitmask = 0x0F; + uint8_t username_max_length = 112; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum = 0; + uint8_t support_user_checksum = 0; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 0xFF; + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(NUMBER_OF_USERS), + &number_of_users, + sizeof(number_of_users)); + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORTED_CREDENTIAL_RULES), + &cred_rule_bitmask, + sizeof(cred_rule_bitmask)); + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(MAX_USERNAME_LENGTH), + &username_max_length, + sizeof(username_max_length)); + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORT_USER_SCHEDULE), + &support_user_schedule, + sizeof(support_user_schedule)); + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORT_ALL_USERS_CHECKSUM), + &support_all_users_checksum, + sizeof(support_all_users_checksum)); + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORT_USER_CHECKSUM), + &support_user_checksum, + sizeof(support_user_checksum)); + + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORTED_USER_TYPES), + &supported_user_types_bitmask, + sizeof(supported_user_types_bitmask)); +} + +void setup_cred_capabilities() +{ + // Supports ZCL_CRED_TYPE_PIN_CODE..ZCL_CRED_TYPE_UWB + // Adjust if needed, we don't need to test all types and this outputs a lot of noise on the logs + uint8_t max_cred_type = ZCL_CRED_TYPE_UWB; + for (uint8_t i = ZCL_CRED_TYPE_PIN_CODE; i <= max_cred_type; i++) { + user_credential_type_t cred_type = static_cast(i); + + auto supported_cred_type_node + = attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + &cred_type, + sizeof(cred_type)); + uint8_t crb_support = 1; + uint16_t slot_supported = 0xFFFF; + uint8_t cred_min_length = 0; + uint8_t cred_max_length = 0xFF; + uint8_t learn_timeout = 112; + uint8_t learn_steps = 12; + + mock_expected_cred_rule_mqtt_topic(cred_type, + "LearnSupport", + (bool)crb_support); + attribute_store_emplace(supported_cred_type_node, + ATTRIBUTE(CREDENTIAL_LEARN_SUPPORT), + &crb_support, + sizeof(crb_support)); + + mock_expected_cred_rule_mqtt_topic(cred_type, + "SupportedSlotCount", + slot_supported); + + attribute_store_emplace(supported_cred_type_node, + ATTRIBUTE(CREDENTIAL_SUPPORTED_SLOT_COUNT), + &slot_supported, + sizeof(slot_supported)); + mock_expected_cred_rule_mqtt_topic(cred_type, + "CredentialMinLength", + cred_min_length); + + attribute_store_emplace(supported_cred_type_node, + ATTRIBUTE(CREDENTIAL_MIN_LENGTH), + &cred_min_length, + sizeof(cred_min_length)); + + mock_expected_cred_rule_mqtt_topic(cred_type, + "CredentialMaxLength", + cred_max_length); + attribute_store_emplace(supported_cred_type_node, + ATTRIBUTE(CREDENTIAL_MAX_LENGTH), + &cred_max_length, + sizeof(cred_max_length)); + + mock_expected_cred_rule_mqtt_topic(cred_type, + "LearnRecommendedTimeout", + learn_timeout); + attribute_store_emplace(supported_cred_type_node, + ATTRIBUTE(CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT), + &learn_timeout, + sizeof(learn_timeout)); + + mock_expected_cred_rule_mqtt_topic(cred_type, + "LearnNumberOfSteps", + learn_steps); + attribute_store_emplace(supported_cred_type_node, + ATTRIBUTE(CREDENTIAL_LEARN_NUMBER_OF_STEPS), + &learn_steps, + sizeof(learn_steps)); + + // Will allow to test deletion of attributes + created_supported_credential_types.push_back(cred_type); + } +} + +///////////////////////////////////////////////////////////////////////// +// HELPERS +///////////////////////////////////////////////////////////////////////// +extern "C" { + +void helper_test_operation_type(attribute_store_node_t parent_node, + user_credential_operation_type_t operation_type, + attribute_store_type_t tested_attribute_type + = 0) +{ + if (tested_attribute_type == 0) { + tested_attribute_type = ATTRIBUTE(USER_OPERATION_TYPE); + // If we are testing a credential we test its attribute instead + if (attribute_store_get_node_type(parent_node) + != ATTRIBUTE(USER_UNIQUE_ID)) { + tested_attribute_type = ATTRIBUTE(CREDENTIAL_OPERATION_TYPE); + } + } + attribute_store_node_t operation_type_node + = attribute_store_get_first_child_by_type(parent_node, + tested_attribute_type); + user_credential_operation_type_t reported_operation_type; + attribute_store_get_desired(operation_type_node, + &reported_operation_type, + sizeof(reported_operation_type)); + + TEST_ASSERT_EQUAL_MESSAGE(operation_type, + reported_operation_type, + "Operation Type mismatch"); +} + +attribute_store_node_t + helper_add_user_id(user_credential_user_unique_id_t user_unique_id) +{ + return attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + &user_unique_id, + sizeof(user_unique_id)); +} + +// This function will test the MQTT topics for an user +attribute_store_node_t helper_add_complete_user( + user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + user_credential_user_active_state_t user_active_state, + user_credential_expiring_timeout_minutes_t expiring_timeout, + user_credential_user_name_encoding_t user_name_encoding, + const char *user_name) +{ + attribute_store_node_t user_id_node = helper_add_user_id(user_id); + + mock_expected_user_mqtt_topic(user_id, + "UserType", + user_type_enum_get_enum_value_name(user_type)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_TYPE), + &user_type, + sizeof(user_type)); + + mock_expected_user_mqtt_topic(user_id, + "CredentialRule", + cred_rule_get_enum_value_name(credential_rule)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(CREDENTIAL_RULE), + &credential_rule, + sizeof(credential_rule)); + + mock_expected_user_mqtt_topic(user_id, + "UserActiveState", + static_cast(user_active_state)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_ACTIVE_STATE), + &user_active_state, + sizeof(user_active_state)); + + mock_expected_user_mqtt_topic(user_id, + "ExpiringTimeoutMinutes", + static_cast(expiring_timeout)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES), + &expiring_timeout, + sizeof(expiring_timeout)); + + mock_expected_user_mqtt_topic( + user_id, + "UserNameEncoding", + user_name_encoding_type_get_enum_value_name(user_name_encoding)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_NAME_ENCODING), + &user_name_encoding, + sizeof(user_name_encoding)); + + std::string cpp_str_username(user_name); + mock_expected_user_mqtt_topic(user_id, "UserName", cpp_str_username); + attribute_store_node_t user_name_node + = attribute_store_add_node(ATTRIBUTE(USER_NAME), user_id_node); + attribute_store_set_reported_string(user_name_node, user_name); + + // Reported attributes by the end device + // Need those to test MQTT topics + user_credential_modifier_node_id_t modifier_node_id = 1212; + user_credential_modifier_type_t modifier_type + = ZCL_USER_MODIFIER_TYPE_LOCALLY; + mock_expected_user_mqtt_topic(user_id, + "UserModifierNodeId", + static_cast(modifier_node_id)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_MODIFIER_NODE_ID), + &modifier_node_id, + sizeof(modifier_node_id)); + mock_expected_user_mqtt_topic( + user_id, + "UserModifierType", + user_modifier_type_get_enum_value_name(modifier_type)); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_MODIFIER_TYPE), + &modifier_type, + sizeof(modifier_type)); + + // Only used to see if they are correctly exposed + user_credential_checksum_t user_checksum = 0xABCD; + mock_expected_user_mqtt_topic( + user_id, + "UserChecksum", + user_checksum); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_CHECKSUM), + &user_checksum, + sizeof(user_checksum)); + user_credential_checksum_t computed_checksum = 0xFFFF; + mock_expected_user_mqtt_topic( + user_id, + "UserChecksumError", + computed_checksum); + attribute_store_emplace(user_id_node, + ATTRIBUTE(USER_CHECKSUM_MISMATCH_ERROR), + &computed_checksum, + sizeof(computed_checksum)); + + // Cleanup : this will automatically test the MQTT deletion messages + created_user_id.push_back(user_id); + + return user_id_node; +} + +// This function will test the MQTT topics for a credential +attribute_store_node_t + helper_add_complete_credential(user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const char *credential_data) +{ + attribute_store_node_t user_id_node = helper_add_user_id(user_id); + + attribute_store_node_t credential_type_node + = attribute_store_emplace(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + &credential_type, + sizeof(credential_type)); + + attribute_store_node_t credential_slot_node + = attribute_store_emplace(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + &credential_slot, + sizeof(credential_slot)); + + std::vector credential_data_vector; + std::string cpp_str_credential_data(credential_data); + + if (credential_type == ZCL_CRED_TYPE_PASSWORD) { + std::wstring_convert, char16_t> cnv; + std::u16string credential_data_utf16 + = cnv.from_bytes(cpp_str_credential_data); + + for (const auto &c: credential_data_utf16) { + credential_data_vector.push_back((uint8_t)(c >> 8)); + credential_data_vector.push_back((uint8_t)c); + } + } else { + credential_data_vector + = std::vector(cpp_str_credential_data.begin(), + cpp_str_credential_data.end()); + } + + mock_expected_cred_mqtt_topic( + user_id, + credential_type, + credential_slot, + "CredentialData", + // Credential data is published in UTF-8 no matter what the encoding is + cpp_str_credential_data); + attribute_store_emplace(credential_slot_node, + ATTRIBUTE(CREDENTIAL_DATA), + credential_data_vector.data(), + credential_data_vector.size()); + + // Test association status exposure (will not be used anywhere, it is here to test the MQTT exposure) + uint8_t association_status = 0; + mock_expected_cred_mqtt_topic( + user_id, + credential_type, + credential_slot, + "AssociationStatus", + association_status); + attribute_store_emplace(credential_slot_node, + ATTRIBUTE(ASSOCIATION_STATUS), + &association_status, + sizeof(association_status)); + + // Test credential learn status exposure (will not be used anywhere, it is here to test the MQTT exposure) + uint8_t credential_learn_status = 1; + mock_expected_cred_mqtt_topic( + user_id, + credential_type, + credential_slot, + "CredentialLearnStatus", + credential_learn_status); + attribute_store_emplace(credential_slot_node, + ATTRIBUTE(CREDENTIAL_LEARN_STATUS), + &credential_learn_status, + sizeof(credential_learn_status)); + + // Generated by end device + user_credential_modifier_node_id_t modifier_node_id = 1212; + user_credential_modifier_type_t modifier_type = ZCL_USER_MODIFIER_TYPE_DNE; + + mock_expected_cred_mqtt_topic(user_id, + credential_type, + credential_slot, + "CredentialModifierNodeId", + static_cast(modifier_node_id)); + attribute_store_emplace(credential_slot_node, + ATTRIBUTE(CREDENTIAL_MODIFIER_NODE_ID), + &modifier_node_id, + sizeof(modifier_node_id)); + mock_expected_cred_mqtt_topic( + user_id, + credential_type, + credential_slot, + "CredentialModifierType", + user_modifier_type_get_enum_value_name(modifier_type)); + attribute_store_emplace(credential_slot_node, + ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE), + &modifier_type, + sizeof(modifier_type)); + + // Cleanup : this will automatically test the MQTT deletion messages + created_credential_ids.push_back({user_id, credential_type, credential_slot}); + + return user_id_node; +} + +void helper_test_desired_user_attributes( + attribute_store_node_t user_id_node, + UserTypeEnum user_type, + bool user_active_state, + CredRule credential_rule, + const char *user_name, + UserNameEncodingType user_name_encoding, + uint16_t expiring_timeout) +{ + // User Type + attribute_store_node_t user_type_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_TYPE)); + user_credential_type_t reported_user_type; + attribute_store_get_desired(user_type_node, + &reported_user_type, + sizeof(reported_user_type)); + TEST_ASSERT_EQUAL_MESSAGE(user_type, + reported_user_type, + "User Type mismatch"); + + // User Active State + attribute_store_node_t user_active_state_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_ACTIVE_STATE)); + user_credential_user_active_state_t reported_user_active_state; + attribute_store_get_desired(user_active_state_node, + &reported_user_active_state, + sizeof(reported_user_active_state)); + TEST_ASSERT_EQUAL_MESSAGE(user_active_state, + reported_user_active_state, + "User Active State mismatch"); + // Credential rule + attribute_store_node_t credential_rule_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(CREDENTIAL_RULE)); + user_credential_rule_t reported_credential_rule; + attribute_store_get_desired(credential_rule_node, + &reported_credential_rule, + sizeof(reported_credential_rule)); + TEST_ASSERT_EQUAL_MESSAGE(credential_rule, + reported_credential_rule, + "Credential Rule mismatch"); + + // User Name + attribute_store_node_t user_name_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_NAME)); + char reported_user_name[255]; + attribute_store_get_desired_string(user_name_node, reported_user_name, 255); + TEST_ASSERT_EQUAL_STRING_MESSAGE(user_name, + reported_user_name, + "User Name mismatch"); + + // User Name Encoding + attribute_store_node_t user_name_encoding_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_NAME_ENCODING)); + user_credential_user_name_encoding_t reported_user_name_encoding; + attribute_store_get_desired(user_name_encoding_node, + &reported_user_name_encoding, + sizeof(reported_user_name_encoding)); + TEST_ASSERT_EQUAL_MESSAGE(user_name_encoding, + reported_user_name_encoding, + "User Name Encoding mismatch"); + + // Expiring Timeout + attribute_store_node_t expiring_timeout_node + = attribute_store_get_first_child_by_type( + user_id_node, + ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES)); + user_credential_expiring_timeout_minutes_t reported_expiring_timeout; + attribute_store_get_desired(expiring_timeout_node, + &reported_expiring_timeout, + sizeof(reported_expiring_timeout)); + TEST_ASSERT_EQUAL_MESSAGE(expiring_timeout, + reported_expiring_timeout, + "Expiring Timeout mismatch"); +} + +void helper_test_desired_credential_attributes( + user_credential_user_unique_id_t user_id_node, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const char *credential_data, + bool desired_credential_identifiers, + user_credential_operation_type_t credential_operation_type) +{ + attribute_store_node_value_state_t credential_identifier_state + = desired_credential_identifiers ? DESIRED_ATTRIBUTE : REPORTED_ATTRIBUTE; + + // Credential type + attribute_store_node_t credential_type_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE)); + user_credential_type_t reported_credential_type; + attribute_store_read_value(credential_type_node, + REPORTED_ATTRIBUTE, + &reported_credential_type, + sizeof(reported_credential_type)); + TEST_ASSERT_EQUAL_MESSAGE(credential_type, + reported_credential_type, + "Credential Type mismatch"); + + // Credential Slot + attribute_store_node_t credential_slot_node + = attribute_store_get_first_child_by_type(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT)); + user_credential_slot_t reported_credential_slot; + attribute_store_read_value(credential_slot_node, + credential_identifier_state, + &reported_credential_slot, + sizeof(reported_credential_slot)); + TEST_ASSERT_EQUAL_MESSAGE(credential_slot, + reported_credential_slot, + "Credential Slot mismatch"); + + std::vector expected_credential_data_vector; + std::string str_credential_data(credential_data); + + // CC:0083.01.0A.11.021 Passwords MUST be transmitted in Unicode UTF-16 format, in big endian order + if (credential_type == ZCL_CRED_TYPE_PASSWORD) { + std::wstring_convert, char16_t> cnv; + std::u16string utf16_cred_data = cnv.from_bytes(str_credential_data); + if (cnv.converted() < str_credential_data.size()) + TEST_FAIL_MESSAGE("Can't convert password to utf-16"); + + for (const auto &c: utf16_cred_data) { + expected_credential_data_vector.push_back((uint8_t)(c >> 8)); + expected_credential_data_vector.push_back((uint8_t)c); + } + } else { + expected_credential_data_vector + = std::vector(str_credential_data.begin(), + str_credential_data.end()); + } + + // Credential Data + attribute_store::attribute credential_data_node + = attribute_store_get_first_child_by_type(credential_slot_node, + ATTRIBUTE(CREDENTIAL_DATA)); + std::vector reported_credential_data + = credential_data_node + .desired>(); + + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected_credential_data_vector.data(), + reported_credential_data.data(), + expected_credential_data_vector.size(), + "Credential Data mismatch"); + + // Operation type + helper_test_operation_type(credential_slot_node, credential_operation_type); +} + +void helper_test_user_id(attribute_store_node_t user_id_node, + user_credential_user_unique_id_t user_unique_id, + attribute_store_node_value_state_t value_state) +{ + user_credential_user_unique_id_t reported_user_id; + attribute_store_read_value(user_id_node, + value_state, + &reported_user_id, + sizeof(reported_user_id)); + TEST_ASSERT_EQUAL_MESSAGE(user_unique_id, + reported_user_id, + "User ID mismatch"); +} + +///////////////////////////////////////////////////////////////////////// +// Test cases +///////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////// +// Add user +/////////////////////////////////////////////////// +void test_user_credential_cluster_add_user_not_supported() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_PROGRAMMING_USER; + CredRule credential_rule = ZCL_CRED_RULE_DUAL; + bool user_active_state = false; + uint16_t expiring_timeout = 0; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_UTF_16; + const char *user_name = "V16 TUNING PRO MAX"; + + // Support check + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + 0, // User ID 0 is reserved + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "User 0 is reserved so it should " + "return SL_STATUS_FAIL"); + + // Simulate user + helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "User 12 is existing so it should return SL_STATUS_FAIL"); +} + +void test_user_credential_cluster_add_user_happy_case() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_PROGRAMMING_USER; + CredRule credential_rule = ZCL_CRED_RULE_DUAL; + bool user_active_state = false; + uint16_t expiring_timeout = 0; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_UTF_16; + const char *user_name = "ENDIVE BOOSTER TURBO MAX"; + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + add_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "User 12 is not existing so it should return SL_STATUS_OK"); + + // Test attribute tree state + // All attributes should be set as desired + // User ID + attribute_store_node_t user_id_node + = attribute_store_get_first_child_by_type(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID)); + + helper_test_user_id(user_id_node, user_unique_id, DESIRED_ATTRIBUTE); + helper_test_desired_user_attributes(user_id_node, + user_type, + user_active_state, + credential_rule, + user_name, + user_name_encoding, + expiring_timeout); + + helper_test_operation_type(user_id_node, USER_CREDENTIAL_OPERATION_TYPE_ADD); +} + +/////////////////////////////////////////////////// +// Modify user +/////////////////////////////////////////////////// +void test_user_credential_cluster_modify_user_not_supported() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_PROGRAMMING_USER; + CredRule credential_rule = ZCL_CRED_RULE_DUAL; + bool user_active_state = false; + uint16_t expiring_timeout = 0; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_UTF_16; + const char *user_name = "VROUM VROUM"; + + // Support check + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + modify_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "User 12 doesn't exists so it should return SL_STATUS_FAIL"); +} + +void test_user_credential_cluster_modify_user_with_expiring_timeout() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_EXPIRING_USER; + CredRule credential_rule = ZCL_CRED_RULE_SINGLE; + bool user_active_state = true; + uint16_t expiring_timeout = 50; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII; + const char *user_name = "TURBO MAX CANON"; + // Since we are updating to a ZCL_USER_TYPE_ENUM_DISPOSABLE_USER, expiring_timeout should not be updated + attribute_store_node_t user_id_node + = helper_add_complete_user(user_unique_id, + ZCL_USER_TYPE_ENUM_DISPOSABLE_USER, + ZCL_CRED_RULE_TRIPLE, + user_active_state, + expiring_timeout, + user_name_encoding, + "DEFINITELY NOT TURBO"); + + // Execute command + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + modify_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "User 12 exists so it should return SL_STATUS_OK"); + + // Test attribute tree state + // All attributes should be set as desired except for user id + helper_test_user_id(user_id_node, user_unique_id, REPORTED_ATTRIBUTE); + helper_test_desired_user_attributes(user_id_node, + user_type, + user_active_state, + credential_rule, + user_name, + user_name_encoding, + expiring_timeout); + helper_test_operation_type(user_id_node, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); +} + +void test_user_credential_cluster_modify_user_without_expiring_timeout() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_DISPOSABLE_USER; + CredRule credential_rule = ZCL_CRED_RULE_SINGLE; + bool user_active_state = true; + uint16_t expiring_timeout = 50; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII; + const char *user_name = "Test User"; + + attribute_store_node_t user_id_node + = helper_add_complete_user(user_unique_id, + ZCL_USER_TYPE_ENUM_EXPIRING_USER, + ZCL_CRED_RULE_DUAL, + user_active_state, + 0, + user_name_encoding, + "Test User Original"); + + // Force timeout attribute to 0 and we'll check if that has moved or not + expiring_timeout = 0; + attribute_store_set_child_desired(user_id_node, + ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES), + &expiring_timeout, + sizeof(expiring_timeout)); + // Execute command + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + modify_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "User 12 exists so it should return SL_STATUS_OK"); + + // Test attribute tree state + // All attributes should be set as desired except for user id + helper_test_user_id(user_id_node, user_unique_id, REPORTED_ATTRIBUTE); + helper_test_desired_user_attributes( + user_id_node, + user_type, + user_active_state, + credential_rule, + user_name, + user_name_encoding, + // Force to 0 here since it should not be modified + 0); + helper_test_operation_type(user_id_node, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); +} + +/////////////////////////////////////////////////// +// Delete user +/////////////////////////////////////////////////// + +void test_user_credential_cluster_delete_user_not_supported() +{ + // Support check + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + delete_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + 12), + "User 12 doesn't exists so it should return SL_STATUS_FAIL"); +} + +void test_user_credential_cluster_delete_user_happy_case() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_EXPIRING_USER; + CredRule credential_rule = ZCL_CRED_RULE_SINGLE; + bool user_active_state = true; + uint16_t expiring_timeout = 50; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII; + const char *user_name = "RIP JACKIE TUNNING"; + + auto user_unique_id_node = helper_add_complete_user(user_unique_id, + user_type, + credential_rule, + user_active_state, + expiring_timeout, + user_name_encoding, + user_name); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id), + "Should be able to mark user 12 for deletion"); + + helper_test_operation_type(user_unique_id_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +/////////////////////////////////////////////////// +// Add credential +/////////////////////////////////////////////////// +void test_user_credential_cluster_add_credential_not_supported() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + + // Support check + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, // Non existing user + CredType::ZCL_CRED_TYPE_BLE, + 1, + "Test Credential"), + "User 12 is not existing so it should return SL_STATUS_FAIL"); + + // Simulate user + helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + static_cast(0), // Reserved + 1, + "Test Credential"), + "Credential type 0 is reserved so it should return SL_STATUS_FAIL"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + CredType::ZCL_CRED_TYPE_PIN_CODE, + 0, // Reserved + "Test Credential"), + "Credential slot 0 is reserved so it should return SL_STATUS_FAIL"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + CredType::ZCL_CRED_TYPE_PIN_CODE, + 1, + "1234567ABCDEF"), + "PINCode contains invalid char, it should return SL_STATUS_FAIL"); +} + +void test_user_credential_cluster_add_credential_pin_code_happy_case() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + const char *credential_data = "123456789"; + + // Add simple user + helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + credential_data), + "Should be able to add a new credential"); + + // Test attribute tree state + // All attributes should be set as desired + // User ID + attribute_store_node_t user_id_node + = attribute_store_get_first_child_by_type(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID)); + + helper_test_user_id(user_id_node, user_unique_id, REPORTED_ATTRIBUTE); + helper_test_desired_credential_attributes(user_id_node, + credential_type, + credential_slot, + credential_data, + true, + USER_CREDENTIAL_OPERATION_TYPE_ADD); +} + +void test_user_credential_cluster_add_credential_password_happy_case() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PASSWORD; + user_credential_slot_t credential_slot = 1; + const char *credential_data = "hunter2"; + + // Add simple user + helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + credential_data), + "Should be able to add a new credential"); + + // Test attribute tree state + // All attributes should be set as desired + // User ID + attribute_store_node_t user_id_node + = attribute_store_get_first_child_by_type(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID)); + + helper_test_user_id(user_id_node, user_unique_id, REPORTED_ATTRIBUTE); + helper_test_desired_credential_attributes(user_id_node, + credential_type, + credential_slot, + credential_data, + true, + USER_CREDENTIAL_OPERATION_TYPE_ADD); +} + +void test_user_credential_cluster_add_credential_others_happy_case() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_RFID_CODE; + user_credential_slot_t credential_slot = 1; + const char *credential_data = "hunter2"; + + // Add simple user + helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + add_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + credential_data), + "Should be able to add a new credential"); + + // Test attribute tree state + // All attributes should be set as desired + // User ID + attribute_store_node_t user_id_node + = attribute_store_get_first_child_by_type(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID)); + + helper_test_user_id(user_id_node, user_unique_id, REPORTED_ATTRIBUTE); + helper_test_desired_credential_attributes(user_id_node, + credential_type, + credential_slot, + credential_data, + true, + USER_CREDENTIAL_OPERATION_TYPE_ADD); +} + +/////////////////////////////////////////////////// +// Modify credential +/////////////////////////////////////////////////// +void test_user_credential_cluster_modify_credential_not_supported() +{ + // Simulate Credential + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + + // Support check + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, // Non existing user + credential_type, + credential_slot, + ""), + "User 12 doesn't exists so it should return SL_STATUS_FAIL"); + + // Simulate user + auto user_id_node = helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + ""), + "Credential type doesn't exists so it should return SL_STATUS_FAIL"); + + user_credential_type_t credential_type_c + = static_cast(credential_type); + auto credential_type_node + = attribute_store_emplace(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + &credential_type_c, + sizeof(credential_type_c)); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + ""), + "Credential slot doesn't exists so it should return SL_STATUS_FAIL"); + + attribute_store_emplace(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + &credential_slot, + sizeof(credential_slot)); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + CredType::ZCL_CRED_TYPE_PIN_CODE, + 1, + "1234567ABCDEF"), + "PINCode contains invalid char, it should return SL_STATUS_FAIL"); +} + +void test_user_credential_cluster_modify_credential_pin_code_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + std::string credential_data = "123456789"; + + auto user_id_node = helper_add_complete_credential(user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()); + + credential_data = "12"; + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()), + "Should be able to modify a credential"); + + helper_test_desired_credential_attributes( + user_id_node, + credential_type, + credential_slot, + credential_data.c_str(), + false, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); +} + +void test_user_credential_cluster_modify_credential_password_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PASSWORD; + user_credential_slot_t credential_slot = 12; + std::string credential_data = "hunter2"; + + auto user_id_node = helper_add_complete_credential(user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()); + // Test UTF-16 conversion for password + credential_data = "🔥MAX SPEED TURBO🔥"; + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()), + "Should be able to modify a credential"); + + helper_test_desired_credential_attributes( + user_id_node, + credential_type, + credential_slot, + credential_data.c_str(), + false, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); +} + +void test_user_credential_cluster_modify_credential_others_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_BLE; + user_credential_slot_t credential_slot = 2; + std::string credential_data = "FAST TURBO ENGINE DOG PRO MAX"; + + auto user_id_node = helper_add_complete_credential(user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()); + // Test UTF-16 conversion for password + credential_data = "FAE124A54E5F9325874A23E3646B"; + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + modify_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()), + "Should be able to modify a credential"); + + helper_test_desired_credential_attributes( + user_id_node, + credential_type, + credential_slot, + credential_data.c_str(), + false, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); +} + +/////////////////////////////////////////////////// +// Delete credential +/////////////////////////////////////////////////// +void test_user_credential_cluster_delete_credential_not_supported() +{ + // Simulate Credential + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + + // Support check + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + delete_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, // Non existing user + credential_type, + credential_slot), + "User 12 doesn't exists so it should return SL_STATUS_FAIL"); + + // Simulate user + auto user_id_node = helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + delete_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot), + "Credential type doesn't exists so it should return SL_STATUS_FAIL"); + + user_credential_type_t credential_type_c + = static_cast(credential_type); + auto credential_type_node + = attribute_store_emplace(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + &credential_type_c, + sizeof(credential_type_c)); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + delete_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot), + "Credential slot doesn't exists so it should return SL_STATUS_FAIL"); + + attribute_store_emplace(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + &credential_slot, + sizeof(credential_slot)); +} + +void test_user_credential_cluster_delete_credential_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + CredType credential_type = CredType::ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + std::string credential_data = "12121212"; + + auto user_id_node = helper_add_complete_credential(user_unique_id, + credential_type, + credential_slot, + credential_data.c_str()); + + auto credential_type_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE)); + auto credential_slot_node + = attribute_store_get_first_child_by_type(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT)); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_credential_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + credential_type, + credential_slot), + "Should be able to mark credential for deletion"); + + helper_test_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +void test_user_credential_cluster_delete_all_users_happy_case() +{ + // Simulate user + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_EXPIRING_USER; + CredRule credential_rule = ZCL_CRED_RULE_SINGLE; + bool user_active_state = true; + uint16_t expiring_timeout = 50; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII; + const char *user_name = "RIP JACKIE TUNNING"; + + helper_add_complete_user(user_unique_id, + user_type, + credential_rule, + user_active_state, + expiring_timeout, + user_name_encoding, + user_name); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_all_users_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL), + "Should be able to setup attribute store for all user deletion"); + + user_unique_id = 0; + auto deletion_user_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_user_node), + "Should be one user node with desired value of 0 to " + "perform user interview"); + helper_test_operation_type(deletion_user_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +void test_user_credential_cluster_delete_all_credential_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 0; + user_credential_type_t credential_type = 0; + user_credential_slot_t credential_slot = 0; + + std::vector user_ids = {12, 12, 12, 15, 19}; + std::vector credential_types = {1, 1, 2, 5, 1}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + helper_add_complete_credential(user_ids[i], + credential_types[i], + credential_slots[i], + "1"); + } + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_all_credentials_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL), + "Should be able to setup attribute store for all credential deletion"); + + auto deletion_user_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + auto deletion_cred_type_node + = attribute_store_get_node_child_by_value(deletion_user_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto deletion_cred_slot_node + = attribute_store_get_node_child_by_value(deletion_cred_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_slot, + sizeof(credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_user_node), + "User node with id 0 should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_type_node), + "Credential type node with id 0 should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_slot_node), + "Credential slot node with id 0 should exists"); + + helper_test_operation_type(deletion_cred_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +void test_user_credential_cluster_delete_all_credential_for_user_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + user_credential_type_t credential_type = 0; + user_credential_slot_t credential_slot = 0; + + std::vector user_ids + = {user_unique_id, user_unique_id, user_unique_id, 15, 19}; + std::vector credential_types = {1, 1, 2, 5, 1}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + helper_add_complete_credential(user_ids[i], + credential_types[i], + credential_slots[i], + "1"); + } + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_all_credentials_for_user_command( + supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id), + "Should be able to setup attribute store for all credential deletion"); + + auto deletion_user_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + auto deletion_cred_type_node + = attribute_store_get_node_child_by_value(deletion_user_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto deletion_cred_slot_node + = attribute_store_get_node_child_by_value(deletion_cred_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_slot, + sizeof(credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_user_node), + "User node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_type_node), + "Credential type node with id 0 should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_slot_node), + "Credential slot node with id 0 should exists"); + + helper_test_operation_type(deletion_cred_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +void test_user_credential_cluster_delete_all_credential_for_user_by_type_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + user_credential_type_t credential_type = 1; + user_credential_slot_t credential_slot = 0; + + std::vector user_ids + = {user_unique_id, user_unique_id, user_unique_id, 15, 19}; + std::vector credential_types + = {credential_type, credential_type, 2, 5, credential_type}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + helper_add_complete_credential(user_ids[i], + credential_types[i], + credential_slots[i], + "1"); + } + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_all_credentials_for_user_by_type_command( + supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + static_cast(credential_type)), + "Should be able to setup attribute store for all credential deletion"); + + auto deletion_user_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + auto deletion_cred_type_node + = attribute_store_get_node_child_by_value(deletion_user_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto deletion_cred_slot_node + = attribute_store_get_node_child_by_value(deletion_cred_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_slot, + sizeof(credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_user_node), + "User node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_type_node), + "Credential type node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_slot_node), + "Credential slot node with id 0 should exists"); + + helper_test_operation_type(deletion_cred_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +void test_user_credential_cluster_delete_all_credential_by_type_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 0; + user_credential_type_t credential_type = 1; + user_credential_slot_t credential_slot = 0; + + std::vector user_ids = {12, 12, 12, 15, 19}; + std::vector credential_types + = {credential_type, credential_type, 2, 5, credential_type}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + helper_add_complete_credential(user_ids[i], + credential_types[i], + credential_slots[i], + "1"); + } + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_all_credentials_by_type_command( + supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + static_cast(credential_type)), + "Should be able to setup attribute store for all credential deletion"); + + auto deletion_user_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + auto deletion_cred_type_node + = attribute_store_get_node_child_by_value(deletion_user_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto deletion_cred_slot_node + = attribute_store_get_node_child_by_value(deletion_cred_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_slot, + sizeof(credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_user_node), + "User node with id 0 should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_type_node), + "Credential type node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(deletion_cred_slot_node), + "Credential slot node with id 0 should exists"); + + helper_test_operation_type(deletion_cred_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); +} + +/////////////////////////////////////////////////// +// Learn Start +/////////////////////////////////////////////////// +void test_user_credential_cluster_learn_start_add_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t expected_timeout = 30; + + helper_add_user_id(user_unique_id); + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + credential_learn_start_add_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + static_cast(credential_type), + credential_slot, + expected_timeout), + "Should be able to setup attribute store for learn start"); + + auto user_id_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + auto credential_type_node + = attribute_store_get_node_child_by_value(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto credential_slot_node + = attribute_store_get_node_child_by_value(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_slot, + sizeof(credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(user_id_node), + "User node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(credential_type_node), + "Credential type node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(credential_slot_node), + "Credential slot should exists"); + + helper_test_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_ADD, + ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE)); + user_credential_learn_timeout_t timeout = 0; + attribute_store_get_child_reported(credential_slot_node, + ATTRIBUTE(CREDENTIAL_LEARN_TIMEOUT), + &timeout, + sizeof(timeout)); + TEST_ASSERT_EQUAL_MESSAGE(expected_timeout, + timeout, + "Timeout value mismatch"); +} + +void test_user_credential_cluster_learn_start_modify_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t expected_timeout = 30; + + helper_add_user_id(user_unique_id); + helper_add_complete_credential(user_unique_id, + credential_type, + credential_slot, + "1234"); + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + credential_learn_start_modify_command( + supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id, + static_cast(credential_type), + credential_slot, + expected_timeout), + "Should be able to setup attribute store for learn start"); + + auto user_id_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&user_unique_id, + sizeof(user_unique_id), + 0); + auto credential_type_node + = attribute_store_get_node_child_by_value(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto credential_slot_node + = attribute_store_get_node_child_by_value(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_slot, + sizeof(credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(user_id_node), + "User node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(credential_type_node), + "Credential type node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(credential_slot_node), + "Credential slot should exists"); + + helper_test_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY, + ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE)); + uint8_t timeout = 0; + attribute_store_get_child_reported(credential_slot_node, + ATTRIBUTE(CREDENTIAL_LEARN_TIMEOUT), + &timeout, + sizeof(timeout)); + TEST_ASSERT_EQUAL_MESSAGE(expected_timeout, + timeout, + "Timeout value mismatch"); +} + +void test_user_credential_cluster_learn_stop_happy_case() +{ + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + credential_learn_stop_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL), + "Should be able to setup attribute store for learn stop"); + + uint8_t stop_flag = 0; + auto stop_node + = attribute_store_get_node_child_by_type(endpoint_id_node, + ATTRIBUTE(CREDENTIAL_LEARN_STOP), + 0); + attribute_store_get_desired(stop_node, &stop_flag, sizeof(stop_flag)); + TEST_ASSERT_EQUAL_MESSAGE(1, stop_flag, "Stop flag should be set to 1"); +} + +void test_user_credential_cluster_credential_association_happy_case() +{ + user_credential_user_unique_id_t source_user_unique_id = 12; + user_credential_user_unique_id_t destination_user_unique_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t source_credential_slot = 1; + user_credential_slot_t destination_credential_slot = 2; + + helper_add_user_id(source_user_unique_id); + helper_add_complete_credential(source_user_unique_id, + credential_type, + source_credential_slot, + "1234"); + helper_add_user_id(destination_user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + credential_association_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + static_cast(credential_type), + source_user_unique_id, + source_credential_slot, + destination_user_unique_id, + destination_credential_slot), + "Should be able to setup attribute store for credential_association"); + + auto user_id_node + = attribute_store_get_node_child_by_value(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + REPORTED_ATTRIBUTE, + (uint8_t *)&source_user_unique_id, + sizeof(source_user_unique_id), + 0); + auto credential_type_node + = attribute_store_get_node_child_by_value(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + REPORTED_ATTRIBUTE, + (uint8_t *)&credential_type, + sizeof(credential_type), + 0); + auto credential_slot_node = attribute_store_get_node_child_by_value( + credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + REPORTED_ATTRIBUTE, + (uint8_t *)&source_credential_slot, + sizeof(source_credential_slot), + 0); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(user_id_node), + "User node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(credential_type_node), + "Credential type node should exists"); + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(credential_slot_node), + "Credential slot should exists"); + + user_credential_user_unique_id_t reported_destination_user_id = 0; + auto association_destination_user_node + = attribute_store_get_node_child_by_type( + credential_slot_node, + ATTRIBUTE(ASSOCIATION_DESTINATION_USER_ID), + 0); + attribute_store_get_desired(association_destination_user_node, + &reported_destination_user_id, + sizeof(reported_destination_user_id)); + TEST_ASSERT_EQUAL_MESSAGE(destination_user_unique_id, + reported_destination_user_id, + "Destination user id mismatch"); + + user_credential_slot_t reported_destination_credential_slot = 0; + auto association_destination_credential_slot_node + = attribute_store_get_node_child_by_type( + credential_slot_node, + ATTRIBUTE(ASSOCIATION_DESTINATION_CREDENTIAL_SLOT), + 0); + attribute_store_get_desired(association_destination_credential_slot_node, + &reported_destination_credential_slot, + sizeof(reported_destination_credential_slot)); + TEST_ASSERT_EQUAL_MESSAGE(destination_credential_slot, + reported_destination_credential_slot, + "Destination credential slot mismatch"); +} + +void test_user_credential_cluster_test_user_checksum_happy_case() +{ + user_credential_user_unique_id_t user_unique_id = 12; + + auto user_id_node = helper_add_user_id(user_unique_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + get_user_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id), + "Should be able to setup attribute store for get_user_checksum"); + + auto checksum_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_CHECKSUM)); + + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(checksum_node), + "Checksum node should exists"); + user_credential_checksum_t checksum = 1312; + mock_expected_user_mqtt_topic(user_unique_id, + "UserChecksum", + checksum); + attribute_store_set_reported(checksum_node, &checksum, sizeof(checksum)); + + // Try a second time to see if we still have only one checksum node + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + get_user_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_unique_id), + "Should be able to setup attribute store for get_user_checksum"); + + auto checksum_count + = attribute_store_get_node_child_count_by_type(user_id_node, + ATTRIBUTE(USER_CHECKSUM)); + + TEST_ASSERT_EQUAL_MESSAGE(1, + checksum_count, + "Should have only one checksum attribute"); + + checksum_node + = attribute_store_get_first_child_by_type(user_id_node, + ATTRIBUTE(USER_CHECKSUM)); + + TEST_ASSERT_FALSE_MESSAGE( + attribute_store_is_reported_defined(checksum_node), + "Checksum node reported value should be not defined"); +} + +void test_user_credential_cluster_test_credential_checksum_happy_case() +{ + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + + auto credential_type_node + = attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + &credential_type, + sizeof(credential_type)); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + get_credential_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + static_cast(credential_type)), + "Should be able to setup attribute store for get_credential_checksum"); + + auto checksum_node + = attribute_store_get_first_child_by_type(credential_type_node, + ATTRIBUTE(CREDENTIAL_CHECKSUM)); + + TEST_ASSERT_TRUE_MESSAGE(attribute_store_node_exists(checksum_node), + "Checksum node should exists"); + + user_credential_checksum_t checksum = 1312; + mock_expected_cred_rule_mqtt_topic(credential_type, + "CredentialChecksum", + checksum); + attribute_store_set_reported(checksum_node, &checksum, sizeof(checksum)); + + // Try a second time to see if we still have only one checksum node + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + get_credential_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + static_cast(credential_type)), + "Should be able to setup attribute store for get_credential_checksum"); + + auto checksum_count + = attribute_store_get_node_child_count_by_type(credential_type_node, + ATTRIBUTE(CREDENTIAL_CHECKSUM)); + + TEST_ASSERT_EQUAL_MESSAGE(1, + checksum_count, + "Should have only one checksum attribute"); + + checksum_node + = attribute_store_get_first_child_by_type(credential_type_node, + ATTRIBUTE(CREDENTIAL_CHECKSUM)); + + TEST_ASSERT_FALSE_MESSAGE( + attribute_store_is_reported_defined(checksum_node), + "Checksum node reported value should be not defined"); +} + + +void test_user_credential_cluster_test_all_users_checksum_happy_case() +{ + // Command not supported yet (default user capabilities SUPPORT_ALL_USERS_CHECKSUM set to 0) + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + get_all_users_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK), + "Not supported yet since we are missing the capability"); + + cpp_endpoint_node.child_by_type(ATTRIBUTE(SUPPORT_ALL_USERS_CHECKSUM)) + .set_reported(1); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + get_all_users_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL), + "Should be able to setup attribute store for get_all_users_checksum"); + + auto checksum_node + = cpp_endpoint_node.child_by_type(ATTRIBUTE(ALL_USERS_CHECKSUM)); + + TEST_ASSERT_TRUE_MESSAGE( + checksum_node.is_valid(), + "All users checksum node should exists"); + + checksum_node.set_desired(1312); + checksum_node.set_reported(12); + + // Try a second time to see if we clear the attributes + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + get_all_users_checksum_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL), + "Should be able to setup attribute store for get_all_users_checksum"); + + TEST_ASSERT_FALSE_MESSAGE( + checksum_node.desired_exists(), + "Checksum node desired value should NOT exists"); + + TEST_ASSERT_FALSE_MESSAGE( + checksum_node.reported_exists(), + "Checksum node reported value should NOT exists"); +} + +void test_user_credential_cluster_test_admin_set_command_happy_case() +{ + auto support_admin_pin_code_node + = cpp_endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE)) + .set_reported(0); + auto status + = set_admin_pin_code_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ""); + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + status, + "Admin set should NOT be supported since SUPPORT_ADMIN_PIN_CODE is 0"); + + support_admin_pin_code_node.set_reported(1); + + status + = set_admin_pin_code_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ""); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Admin set should be supported since SUPPORT_ADMIN_PIN_CODE is 1"); + + std::string expected_pin_code = "1234"; + status + = set_admin_pin_code_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + expected_pin_code.c_str()); + + auto raw_pin_code + = cpp_endpoint_node.child_by_type(ATTRIBUTE(ADMIN_PIN_CODE)) + .desired>(); + + std::string reported_pin_code; + for (char c : raw_pin_code) { + reported_pin_code += c; + } + + TEST_ASSERT_EQUAL_STRING_MESSAGE(expected_pin_code.c_str(), + reported_pin_code.c_str(), + "Admin pin code mismatch"); +} + +void test_user_credential_cluster_test_admin_deactivate_command_happy_case() +{ + auto support_admin_deactivation_node + = cpp_endpoint_node + .emplace_node(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE_DEACTIVATION)) + .set_reported(0); + auto status = deactivate_admin_pin_code_command( + supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Admin deactivation should NOT be supported since " + "SUPPORT_ADMIN_PIN_CODE_DEACTIVATION is 0"); + + support_admin_deactivation_node.set_reported(1); + + status = deactivate_admin_pin_code_command( + supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Admin deactivation should be supported since SUPPORT_ADMIN_PIN_CODE is 1"); + + status + = deactivate_admin_pin_code_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL); + + std::vector expected_empty_pin_code = {0}; + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE( + expected_empty_pin_code.data(), + cpp_endpoint_node.child_by_type(ATTRIBUTE(ADMIN_PIN_CODE)) + .desired>() + .data(), + expected_empty_pin_code.size(), + "Admin pin code should be at empty value"); +} + +/////////////////////////////////////////////////// +// Support tests +/////////////////////////////////////////////////// + +void test_user_credential_cluster_test_user_command_support_happy_case() +{ + // We don't care about those value it should not matter here + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_DISPOSABLE_USER; + CredRule credential_rule = ZCL_CRED_RULE_SINGLE; + bool user_active_state = true; + uint16_t expiring_timeout = 50; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII; + const char *user_name = "Test User"; + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + add_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "Add user should be supported"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + modify_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "Modify user should be supported"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + delete_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_unique_id), + "Delete user should be supported"); +} + +void test_user_credential_cluster_test_user_command_not_supported_happy_case() +{ + // We don't care about those value it should not matter here + user_credential_user_unique_id_t user_unique_id = 12; + UserTypeEnum user_type = ZCL_USER_TYPE_ENUM_DISPOSABLE_USER; + CredRule credential_rule = ZCL_CRED_RULE_SINGLE; + bool user_active_state = true; + uint16_t expiring_timeout = 50; + UserNameEncodingType user_name_encoding = ZCL_USER_NAME_ENCODING_TYPE_ASCII; + const char *user_name = "Test User"; + + // We don't want anything in the tree for this test + // This way we can make support check fails + // We need to inform the MQTT of the deleted credential type rules + for (auto cred_type: created_supported_credential_types) { + mock_deletion_cred_rule_mqtt_topic(cred_type); + } + // Delete all the nodes + attribute_store_delete_all_children(endpoint_id_node); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + add_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "Check value : Add user should not be supported"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + modify_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_unique_id, + user_type, + user_active_state, + credential_rule, + user_name, + expiring_timeout, + user_name_encoding), + "Modify user should not be supported"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + delete_user_command(supporting_node_unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_unique_id), + "Delete user should not be supported"); +} + + +} // extern "C" \ No newline at end of file diff --git a/applications/zpc/components/zcl_cluster_servers/test/workaround_for_test.hpp b/applications/zpc/components/zcl_cluster_servers/test/workaround_for_test.hpp new file mode 100644 index 0000000000..e2b85fb108 --- /dev/null +++ b/applications/zpc/components/zcl_cluster_servers/test/workaround_for_test.hpp @@ -0,0 +1,25 @@ +#ifndef WORKAROUND_FOR_TEST_HPP +#define WORKAROUND_FOR_TEST_HPP + +/* This is a workaround to hide the C++ includes from + * Unity's generate_test_runner.rb +*/ + +#ifdef __cplusplus +#include +#include +#include +#include + +#include +#include +#include + +// UTF16 conversion (deprecated in C++17) +// Needed for credential data (password) per specification +#include +#include + +#include "dotdot_mqtt_helpers.hpp" +#endif +#endif diff --git a/applications/zpc/components/zpc_attribute_store/CMakeLists.txt b/applications/zpc/components/zpc_attribute_store/CMakeLists.txt index 9455dde525..1542c4f508 100644 --- a/applications/zpc/components/zpc_attribute_store/CMakeLists.txt +++ b/applications/zpc/components/zpc_attribute_store/CMakeLists.txt @@ -6,7 +6,10 @@ add_library( src/zpc_attribute_store_register_default_attribute_type_data.cpp src/zpc_attribute_store_type_registration.cpp src/zwave_association_toolbox.cpp - src/zwave_utils.c) + src/zwave_utils.c + src/zwave_frame_parser.cpp + src/zwave_frame_generator.cpp + ) target_include_directories( zpc_attribute_store diff --git a/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h b/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h index 4e660ac304..3fd89fb3a1 100644 --- a/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h +++ b/applications/zpc/components/zpc_attribute_store/include/attribute_store_defined_attribute_types.h @@ -1062,6 +1062,136 @@ DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_INFO_NAME, DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_SOUND_SWITCH_TONE_PLAY, ((COMMAND_CLASS_SOUND_SWITCH << 8) | 0x08)) + +///////////////////////////////////////////////// +// User Credential Command Class +///< This represents the version of the User CredentialCommand class. +/// zwave_cc_version_t +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_VERSION, + ZWAVE_CC_VERSION_ATTRIBUTE(COMMAND_CLASS_USER_CREDENTIAL)) + + +/// > User Capabilities +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_NUMBER_OF_USERS, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x02)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x03)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_MAX_USERNAME_LENGTH, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x04)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_USER_SCHEDULE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x05)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_ALL_USERS_CHECKSUM, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x06)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_USER_CHECKSUM, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x07)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_USER_TYPES, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x08)) + +/// > Credential Capabilities +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x09)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x0A)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x0B)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x0C)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_SUPPORT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x0D)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SUPPORTED_SLOT_COUNT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x0E)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MIN_LENGTH, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x0F)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MAX_LENGTH, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x10)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x11)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_NUMBER_OF_STEPS, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x12)) + +/// > All Users Checksum +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ALL_USERS_CHECKSUM, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x13)) + +/// > Users +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x14)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_MODIFIER_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x15)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_MODIFIER_NODE_ID, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x16)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x17)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_ACTIVE_STATE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x18)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_NAME, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x19)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_NAME_ENCODING, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x1A)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_RULE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x1B)) + +/// > Credentials +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x1C)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_DATA, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x1D)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x1E)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_READ_BACK, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x1F)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MODIFIER_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x20)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MODIFIER_NODE_ID, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x21)) + + +// Specific to Credential SET +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_OPERATION_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x22)) + +// Specific to USER SET +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_OPERATION_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x23)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_EXPIRING_TIMEOUT_MINUTES, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x24)) + +// Specific to Credential Learn +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_OPERATION_TYPE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x25)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_TIMEOUT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x26)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_STATUS, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x27)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_STEPS_REMAINING, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x28)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_STOP, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x29)) + +// Specific to Credential User Unique Identifier Credential (UUIC) Association +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ASSOCIATION_DESTINATION_USER_ID, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x2A)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ASSOCIATION_DESTINATION_CREDENTIAL_SLOT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x2B)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ASSOCIATION_STATUS, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x2C)) + +// Checksums +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_CHECKSUM, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x2D)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_CHECKSUM_MISMATCH_ERROR, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x2E)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_CHECKSUM, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x2F)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_CHECKSUM_MISMATCH_ERROR, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x30)) + +// Admin Code +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ADMIN_PIN_CODE, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x31)) +DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ADMIN_PIN_CODE_OPERATION_RESULT, + ((COMMAND_CLASS_USER_CREDENTIAL << 8) | 0x32)) + ///////////////////////////////////////////////// // Z-Wave Plus Info CC DEFINE_ATTRIBUTE(ATTRIBUTE_COMMAND_ZWAVEPLUS_INFO_VERSION, diff --git a/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_user_credential_types.h b/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_user_credential_types.h new file mode 100644 index 0000000000..1c96efde4b --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/include/command_class_types/zwave_command_class_user_credential_types.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * # License + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +/** + * @defgroup zwave_command_class_user_credential_types Type definitions for attribute storage of the Sound Switch Command Class + * @ingroup zpc_attribute_store_command_classes_types + * @brief Type definitions for the Sound Switch Command Class. + * + * @{ + */ + +#ifndef ZWAVE_COMMAND_CLASS_USER_CREDENTIALS_TYPES_H +#define ZWAVE_COMMAND_CLASS_USER_CREDENTIALS_TYPES_H + +#include + +///> Supported credential rules bitmask. uint8_t +typedef uint8_t user_credential_supported_credential_rules_t; + +///> Supported user type bitmask. uint32_t +typedef uint32_t user_credential_supported_user_type_bitmask_t; + +///> All user checksum. uint16_t +typedef uint16_t user_credential_all_users_checksum_t; + +///> User Unique ID. uint16_t +typedef uint16_t user_credential_user_unique_id_t; +///> User Modifier Type. uint8_t +typedef uint8_t user_credential_modifier_type_t; +///> User Modifier Node ID. uint16_t +typedef uint16_t user_credential_modifier_node_id_t; + +///> User Credential Checksum. uint16_t +typedef uint16_t user_credential_checksum_t; + +///> User Type. uint8_t +#define USER_CREDENTIAL_USER_TYPE_GENERAL_USER 0x00 +#define USER_CREDENTIAL_USER_TYPE_PROGRAMMING_USER 0x03 +#define USER_CREDENTIAL_USER_TYPE_NON_ACCESS_USER 0x04 +#define USER_CREDENTIAL_USER_TYPE_DURESS_USER 0x05 +#define USER_CREDENTIAL_USER_TYPE_DISPOSABLE_USER 0x06 +#define USER_CREDENTIAL_USER_TYPE_EXPIRING_USER 0x07 +#define USER_CREDENTIAL_USER_TYPE_REMOTE_ONLY_USER 0x09 +typedef uint8_t user_credential_user_type_t; +///> User active state (0 or 1). uint8_t +typedef uint8_t user_credential_user_active_state_t; +///> User name encoding. uint8_t +typedef uint8_t user_credential_user_name_encoding_t; + +///> Credential type. uint8_t +typedef uint8_t user_credential_type_t; + +///> Credential rule. uint8_t +typedef uint8_t user_credential_rule_t; + +///> Credential slot. uint16_t +typedef uint16_t user_credential_slot_t; + +///> Operation type. uint8_t +#define USER_CREDENTIAL_OPERATION_TYPE_ADD 0x00 +#define USER_CREDENTIAL_OPERATION_TYPE_MODIFY 0x01 +#define USER_CREDENTIAL_OPERATION_TYPE_DELETE 0x02 +typedef uint8_t user_credential_operation_type_t; + +///> Expiring Timeout for User (Minutes). uint16_t +typedef uint16_t user_credential_expiring_timeout_minutes_t; + +///> Expiring Timeout for Credential Learn (Seconds). uint8_t +typedef uint8_t user_credential_learn_timeout_t; + +///> Credential Learn Status. uint8_t +typedef uint8_t user_credential_learn_status_t; + +///> Full identifier for a user credential. +typedef struct user_credential_credential_identifier { + user_credential_user_unique_id_t user_unique_id; + user_credential_type_t credential_type; + user_credential_slot_t credential_slot; +} user_credential_credential_identifier_t; + +///> Missing definitions +// Admin PIN Code +#define ADMIN_PIN_CODE_SET 0x1A +#define ADMIN_PIN_CODE_GET 0x1B +#define ADMIN_PIN_CODE_REPORT 0x1C +// Admin PIN Code Report +#define ADMIN_PIN_CODE_REPORT_MODIFIED 0x01 +#define ADMIN_PIN_CODE_REPORT_UNMODIFIED 0x03 +#define ADMIN_PIN_CODE_REPORT_RESPONSE_TO_GET 0x04 +#define ADMIN_PIN_CODE_REPORT_DUPLICATE_CREDENTIAL 0x07 +#define ADMIN_PIN_CODE_REPORT_MANUFACTURER_SECURITY_RULE 0x08 +#define ADMIN_PIN_CODE_REPORT_NOT_SUPPORTED 0x0D +#define ADMIN_PIN_CODE_REPORT_DEACTIVATION_NOT_SUPPORTED 0x0E +#define ADMIN_PIN_CODE_REPORT_UNSPECIFIED_ERROR 0x0F + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif //ZWAVE_COMMAND_CLASS_USER_CREDENTIALS_TYPES_H +/** @} end zwave_command_class_user_credentials_types */ diff --git a/applications/zpc/components/zpc_attribute_store/include/zwave_frame_generator.hpp b/applications/zpc/components/zpc_attribute_store/include/zwave_frame_generator.hpp new file mode 100644 index 0000000000..0fe4480d6a --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/include/zwave_frame_generator.hpp @@ -0,0 +1,233 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +/** + * @defgroup zwave_frame_parser C++ Z-Wave Frame Handler Helper + * @brief C++ definitions for handling Z-Wave Frames + * + * This group is used to handle Z-Wave frame and link their contents with the attribute store. + * + * @{ + */ + +#ifndef ZWAVE_FRAME_GENERATOR_HPP +#define ZWAVE_FRAME_GENERATOR_HPP + +#ifdef __cplusplus + +// Unify includes +#include "attribute_store.h" +#include "sl_status.h" + +// Cpp includes +#include + +/** + * @class zwave_frame_generator + * @brief Generate frames for Z-Wave commands based on attribute store values + * + * Mainly used to generate Set or Get frame to send to Z-Wave devices + * + * You can either set raw bytes, or let the function get the value from the attribute store for + * you. You are able to specify if you want a Desired or Reported value. + * + * @code{.cpp} + * // Only needed to be instantiated once + * static zwave_frame_generator frame_generator(COMMAND_CLASS_SWITCH_BINARY); + * + * // On a frame callback : + * static sl_status_t zwave_command_class_set( + * attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) { + * + * // We don't use frame_length here since we need to set it manually + * constexpr uint8_t expected_frame_size = 3; + * try { + * frame_generator.initialize_frame(SWITCH_BINARY_SET, frame, expected_frame_size); + * frame_generator.add_raw_byte(0x01); + * frame_generator.add_value(my_binary_node, REPORTED_ATTRIBUTE); + * + * // Will take the DESIRED_ATTRIBUTE value from my_node and shift it 2 bits to the left, + * // then add 0b1 shifted 7 bits to the left. + * // Result value (if desired value is 0b11) : 0b10001100 + * std::vector values_mix = { + * {.left_shift = 2, + * .node = my_node, + * .node_value_state = DESIRED_ATTRIBUTE}, + * {.left_shift = 7, .raw_value = 0b1}, + * }; + * frame_generator.add_shifted_values(values_mix); + * + * frame_generator.validate_frame(frame_length); + * + * } catch (const std::exception &e) { + * sl_log_error(LOG_TAG, "Error while generating frame : %s", e.what()); + * return SL_STATUS_FAIL; + * } + * + * return SL_STATUS_OK; + * } + * + * @endcode + */ +class zwave_frame_generator +{ + public: + /** + * @brief Represent a value that needs to be shifted before being added to the frame. + * + * You can either specify the node and value state to get the value from the attribute store + * or provide a raw value to be shifted. + * + * @note If you provide a node, it will read a uint8_t value from it. + */ + struct shifted_value { + /** + * @brief The number of bits to shift the value (left) + */ + uint8_t left_shift = 0; + /** + * @brief Node to get the value from (uint8_t). If ATTRIBUTE_STORE_INVALID_NODE, use raw_value + */ + attribute_store_node_t node = ATTRIBUTE_STORE_INVALID_NODE; + /** + * @brief State of the value to get from the node. Only used if node is not ATTRIBUTE_STORE_INVALID_NODE + */ + attribute_store_node_value_state_t node_value_state = REPORTED_ATTRIBUTE; + /** + * @brief Raw value to shift. Only used if node is ATTRIBUTE_STORE_INVALID_NODE + */ + uint8_t raw_value = 0; + }; + + /** + * @brief Constructor + * + * @param zwave_command_class The Z-Wave command class to use in the header of all generated commands + */ + explicit zwave_frame_generator(uint8_t zwave_command_class); + ~zwave_frame_generator() = default; + + /** + * @brief Initialize a new Z-Wave frame on the given data section. + * + * @note This will reset the internal counter to 0 and update the data section provided with other functions. + * + * After calling this function your frame will look like : + * 0: zwave_command_class (from constructor) + * 1: zwave_command_id (from this function) + * + * @param zwave_command_id The Z-Wave command ID to use in the header of the frame + * @param raw_data The data section of the frame (must be allowed an valid from this address to data_size bytes after) + * @param data_size The size of the data section (we use uint16_t to match Unify API) + */ + void initialize_frame(uint8_t zwave_command_id, + uint8_t *raw_data, + uint16_t data_size); + + /** + * @brief Add a raw byte to the Z-Wave frame + * + * @param byte The byte to add to the frame + */ + void add_raw_byte(uint8_t byte); + + /** + * @brief Add the value contained in the given node to the Z-Wave frame + * + * @throws std::runtime_error if the node is invalid or if the value can't be read + * + * @note The size of the value is automatically determined by the attribute store. + * Numerical values will be stored in big-endian (MSB first LSB last). + * Other formats will keep their original order. + * + * @param node The node to get the value from + * @param node_value_state The state of the value to get from the node + * + */ + void add_value(attribute_store_node_t node, + attribute_store_node_value_state_t node_value_state + = REPORTED_ATTRIBUTE); + /** + * @brief Add a shifted value to the Z-Wave frame + * + * You can either specify a raw value to be shifted, or directly pass the attribute + * store node. + * + * @see shifted_value + * + * @param shifted_values The shifted value to add to the frame + */ + void add_shifted_values(const std::vector &shifted_values); + /** + * @brief Add a shifted value to the Z-Wave frame (single value version) + * + * Convenience function to add a single shifted value to the frame. + * + * @see shifted_value + * + * @param shifted_values The shifted value to add to the frame + */ + void add_shifted_values(const shifted_value &shifted_values); + + /** + * @brief Validate the frame length and throw an error if it is not the expected length + * + * @note We don't use bool here since the all the function throw an error if anything goes wrong + * + * @param frame_length Will set the frame length if current frame length is equal to expected length + */ + void validate_frame(uint16_t *frame_length) const; + + /** + * @brief Generate a Z-Wave frame with no arguments + * + * This function is used to generate a Z-Wave frame with no arguments like a simple Get command. + * Since it is used for convenience, this method doesn't throw an exception and return a status instead. + * + * @param zwave_command_id The Z-Wave command ID to use in the header of the frame + * @param raw_data The data section of the frame (must be able to write 2 byte to this address) + * @param frame_length Frame length pointer (set to 2) + * + * @return SL_STATUS_OK if the frame was generated successfully, SL_STATUS_FAIL otherwise + */ + sl_status_t generate_no_args_frame(uint8_t zwave_command_id, + uint8_t *raw_data, + uint16_t *frame_length); + + private: + /** + * @brief Helper function to get the raw data from the attribute store + * + * @note Number will be returned in little-endian (LSB first MSB last) + * + * @param node The node to get the value from + * @param node_value_state The state of the value to get from the node + * + * @return The raw data from the attribute store + */ + std::vector helper_get_raw_data( + attribute_store_node_t node, + attribute_store_node_value_state_t node_value_state) const; + + // Current Z-Wave command class used in the header of all generated commands + const uint8_t current_command_class; + // Vector wrapper around raw frame data. See initialize_frame() + uint8_t *current_zwave_frame; + // Current Z-Wave frame size + uint16_t current_zwave_frame_size = 0; + // Current Z-Wave frame index (we use uint16_t to match Unify API) + uint16_t current_zwave_frame_index = 0; +}; + +#endif // __cplusplus +#endif // ZWAVE_FRAME_GENERATOR_HPP \ No newline at end of file diff --git a/applications/zpc/components/zpc_attribute_store/include/zwave_frame_parser.hpp b/applications/zpc/components/zpc_attribute_store/include/zwave_frame_parser.hpp new file mode 100644 index 0000000000..2eafb45ee0 --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/include/zwave_frame_parser.hpp @@ -0,0 +1,465 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +/** + * @defgroup zwave_frame_parser C++ Z-Wave Frame Handler Helper + * @brief C++ definitions for handling Z-Wave Frames + * + * This group is used to handle Z-Wave frame and link their contents with the attribute store. + * + * @{ + */ + +#ifndef ZWAVE_FRAME_PARSER_HPP +#define ZWAVE_FRAME_PARSER_HPP + +#ifdef __cplusplus + +// Attribute store +#include "attribute_store.h" +#include "attribute.hpp" + +// Unify +#include "sl_log.h" + +// Generic C++ includes +#include +#include +#include +#include + +// Typedef +using zwave_report_bitmask_t = uint32_t; + +/** + * @class zwave_frame_parser + * @brief Parses Z-Wave frames and extracts data from them. + * + * Mainly used to parse report frame from Z-Wave devices. + * + * This class is used to parse Z-Wave frames and store the data in the attribute store. + * It will store the value as reported in the attribute store. + * + * You can also get the raw data from the frame without storage in the attribute store if needed. + * + * This class has an internal index that will be incremented each time a value is read from the frame. + * This index starts at 2. The first two bytes are the command class and the command ID and should be valid by the time you use this class. + * + * Each time you read something, the index will be incremented by the number of bytes read. + * + * @note Each function (when possible) has an overload to store the value in the attribute store. We don't use default arguments to make sure the user is warned if their node is invalid. + * + * @code{.cpp} + + sl_status_t zwave_command_class_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) + { + + // Report Frame structure : + // 0x00 : COMMAND_CLASS + // 0x01 : COMMAND_ID + // 0x02 : REPORT_TYPE + // 0x03 : REPORT_VALUE (MSB) + // 0x04 : REPORT_VALUE (LSB) + + // Use try to catch read errors + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(5)) { + // No need to specify the details of size here it is handled by is_frame_size_valid + sl_log_error("zwave_command_class_report", "Invalid frame size"); + return SL_STATUS_FAIL; + } + + // Read the report type (0x02) + uint8_t report_type = parser.read_byte(); + + // Alternatively you can use the put the value directly in a node + // attribute_store_node_t report_type_node = attribute_store_add_node(ATTRIBUTE_REPORT_TYPE, parent_node); + // uint8_t report_type = parser.read_byte(report_type_node); + + // Read the report value (0x03 and 0x04) + uint16_t report_value = parser.read_sequential(2); + + // Alternatively you can use the put the value directly in a node + // attribute_store_node_t report_value_node = attribute_store_add_node(ATTRIBUTE_REPORT_VALUE, parent_node); + // uint16_t report_value = parser.read_sequential(2, report_value_node); + + // Will trigger an exception since we are out of range + // uint8_t out_of_range = parser.read_byte(); + + } catch(const std::exception& e) { + SL_LOG_ERROR("zwave_command_class_report", "Error while parsing the frame : %s", e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; + } + * @endcode + */ +class zwave_frame_parser +{ + public: + using zwave_parser_bitmask_result = std::map; + + /** + * @brief Contains the bitmask to apply to a byte read from the frame [and the destination node in the attribute store] + */ + struct bitmask_data { + /** + * @brief The bitmask to apply to the byte read from the frame + */ + uint8_t bitmask = 0b00000000; + /** + * @brief The destination node in the attribute store where to store the value. + * Can be ATTRIBUTE_STORE_INVALID_NODE if you don't want to store the value in the attribute store. + */ + attribute_store_node_t destination_node = ATTRIBUTE_STORE_INVALID_NODE; + }; + + /** + * @brief Constructor + * + * @param data The Z-Wave frame to parse. Doesn't take ownership of the data. + * @param length The length of the frame. We use uint16_t to match C API + */ + explicit zwave_frame_parser(const uint8_t *data, uint16_t length); + ~zwave_frame_parser() = default; + + /** + * @brief Check if the frame size equal to the expected size + * + * Good practice is too use this function right after the constructor + * to make sure the frame is valid. + * + * @param min_size Minimal size of the frame. If this is the only parameter, the frame size should be equal to this value. + * @param max_size Maximal size of the frame. If this parameter is set, the frame size should be between min_size and max_size. Default to 0 and will ignore this parameter. + * + * @return true if the frame size is equal to the expected size + * @return false if the frame size is not equal to the expected size + */ + bool is_frame_size_valid(uint8_t min_size, uint8_t max_size = 0) const; + + /** + * @brief Read the next byte from the frame + * + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it. + * + * @exception std::out_of_range if the current index is out of range + * + * @return The byte read from the frame + */ + uint8_t read_byte(); + + /** + * @brief Read the next byte from the frame and store it in the attribute store + * + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it. + * + * @param node The node in the attribute store where to store the value. + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if something goes wrong when storing the value in the attribute store + * + * @return The byte read from the frame + */ + uint8_t read_byte(attribute_store_node_t node); + + /** + * @brief Read a byte from the frame and applies given bitmasks [and store it in the attribute store] + * + * @param bitmask_data The bitmask to apply to the byte read + * + * @warning This function will not differentiate between an invalid node and no node provided. No warning will be issued if the node is invalid. + * + * @code{.cpp} + // Example of usage + const uint8_t tested_frame[] = {0x01, 0x02, 0b10100111}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Create node + attribute_store_node_t size_value_node = attribute_store_add_node(ATTRIBUTE_SIZE, endpoint_node); + + // Read first value + // Store the first value in size_value_node + constexpr uint8_t BITMASK_SIZE = 0b11000000; + constexpr uint8_t BITMASK_PRECISION = 0b00111000; + constexpr uint8_t BITMASK_SCALE = 0b00000011; + + std::vector data = { + {.bitmask = BITMASK_SIZE, .destination_node = size_value_node}, + {.bitmask = BITMASK_PRECISION}, + {.bitmask = BITMASK_SCALE} + }; + // The value of values will be : {BITMASK_SIZE => 0b10, BITMASK_PRECISION => 0b100, BITMASK_SCALE => 0b11} + zwave_parser_bitmask_result bitmask_values = parser.read_byte_with_bitmask(data); + uint8_t precision_value = bitmask_values[BITMASK_PRECISION]; // 0b100 + uint8_t scale_value = bitmask_values[BITMASK_SCALE]; // 0b11 + uint8_t size_value = bitmask_values[BITMASK_SIZE]; // 0b10 + * @endcode + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if something goes wrong when storing the value in the attribute store + * + * @return The byte read from the frame + */ + zwave_parser_bitmask_result + read_byte_with_bitmask(const std::vector &bitmask_data); + + /** + * @brief Read a byte from the frame and applies given bitmask [and store it in the attribute store] + * + * @note This is a convenience function to avoid creating a vector of bitmask_data + * + * @param bitmask_data The bitmask to apply to the bytes read + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if something goes wrong when storing the value in the attribute store + * + * @return The bytes read from the frame + */ + zwave_parser_bitmask_result + read_byte_with_bitmask(const bitmask_data &bitmask_data); + + /** + * @brief Read a bitmask (adaptive size) from the frame + * + * This helper function will read the current value in the frame to determine the bitmask length, then read the given + * bytes and convert it to zwave_report_bitmask_t. + * + * Excepted frame structure : + * current_index : Bitmask length (N=1-4) + * current_index + 1 : Bitmask value 1 + * ... + * current_index + N : Bitmask value N + * + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it. + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if bitmask length is greater than 4 + * + * @return The bitmask read from the frame + */ + zwave_report_bitmask_t read_bitmask(); + + /** + * @brief Read a bitmask (adaptive size) from the frame and store it in the attribute store + * + * This helper function will read the current value in the frame to determine the bitmask length, then read the given + * bytes and convert it to zwave_report_bitmask_t. + * + * Excepted frame structure : + * current_index : Bitmask length (N=1-4) + * current_index + 1 : Bitmask value 1 + * ... + * current_index + N : Bitmask value N + * + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it (to 1 + bitmask size) + * + * @param node The node in the attribute store where to store the value. + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if something goes wrong when storing the value in the attribute store + * @exception std::invalid_argument if bitmask length is greater than 4 + * + * @return The bitmask read from the frame + */ + zwave_report_bitmask_t read_bitmask(attribute_store_node_t node); + + /** + * @brief Convenience function to read a string (ASCII) from the frame + * + * This helper function will read the first byte to determine the string length, then parse the + * string from the frame. + * + * Excepted frame structure : + * current_index : String length + * current_index + 1 : Char 1 + * ... + * current_index + N : Char N + * + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it (to 1 + string size). + * + * @exception std::out_of_range if the current index is out of range + * + * @return The string read from the frame + */ + std::string read_string(); + /** + * @brief Convenience function to read a string (ASCII) from the frame and store in in the attribute store + * + * This helper function will read the first byte to determine the string length, then parse the + * string from the frame. + * + * Excepted frame structure : + * current_index : String length + * current_index + 1 : Char 1 + * ... + * current_index + N : Char N + * + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it (to 1 + string size). + * + * @param node The node in the attribute store where to store the value. + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if something goes wrong when storing the value in the attribute store + * @return The string read from the frame + */ + std::string read_string(attribute_store_node_t node); + + + /** + * @brief Read a sequence of bytes from the frame + * + * @tparam T The type of the value to read. Supported types are int (and unsigned) of any size, std::string, std::vector + * + * @note Calling this function with a numeric type will assume that the MSB is first and LSB is last. + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it by the number of read bytes. + * + * @param bytes_to_read The number of bytes to read + * + * @exception std::out_of_range if the current index is out of range + * + * @return The value read from the frame + */ + template T read_sequential(uint8_t bytes_to_read) + { + static_assert(std::is_integral::value + || std::is_same::value + || std::is_same>::value, + "Unsupported type"); + + T value_from_frame; + if constexpr (std::is_integral::value) { + value_from_frame = 0; + + for (uint8_t i = 0; i < bytes_to_read; i++) { + T current_byte = zwave_report_frame.at(current_index); + // Z-Wave always have MSB first and LSB last + // If we have read 2 bytes : 0x34,0x56 the result should be 0x3456 + // First iteration : 0x34 << 8 = 0x3400 + // Second iteration : 0x56 << 0 = 0x3456 + uint8_t offset = (bytes_to_read - 1 - i) * 8; + value_from_frame |= current_byte << offset; + + current_index++; + } + + // Convert value to signed if needed + // This is used in the case of a signed value that is smaller than the T type + // e.g. int8_t stored in a int32_t. + if constexpr (std::is_signed::value) { + switch (bytes_to_read) { + case 1: + value_from_frame = static_cast(value_from_frame); + break; + case 2: + value_from_frame = static_cast(value_from_frame); + break; + case 4: + value_from_frame = static_cast(value_from_frame); + break; + default: + throw std::runtime_error("Unsupported size for signed value, only " + "1, 2 or 4 are supported"); + } + } + } else if constexpr (std::is_same::value + || std::is_same>::value) { + value_from_frame.resize(bytes_to_read); + for (uint8_t i = 0; i < bytes_to_read; i++) { + value_from_frame[i] = read_byte(); + } + } + return value_from_frame; + } + + /** + * @brief Read a sequence of bytes from the frame and store it in the attribute store + * + * @tparam T The type of the value to read. Supported types are int (and unsigned) of any size, std::string, std::vector + * + * @note Calling this function with a numeric type will assume that the MSB is first and LSB is last. + * @note Calling this function will read the current value in the frame (starting index = 2) and increment it by the number of read bytes. + * + * @param bytes_to_read The number of bytes to read + * @param node The node in the attribute store where to store the value. + * + * @exception std::out_of_range if the current index is out of range + * @exception std::invalid_argument if something goes wrong when storing the value in the attribute store + * + * @return The value read from the frame + */ + template + T read_sequential(uint8_t bytes_to_read, attribute_store_node_t node) + { + T value = read_sequential(bytes_to_read); + helper_store_value(node, value); + return value; + } + + private: + /** + * @brief Helper function to store a value in the attribute store + * + * @tparam T The type of the value to store + * + * Will check if node is invalid, and do nothing if it is. + * + * @param node The node in the attribute store where to store the value + * @param value The value to store + */ + template + void helper_store_value(attribute_store_node_t node, T value) + { + attribute_store::attribute current_attribute(node); + + if (current_attribute.is_valid()) { + current_attribute.set_reported(value); + } else { + sl_log_warning( + "zwave_frame_parser", + "Node does not exist in the attribute store. Not updating value"); + } + } + + /** + * @brief Get trailing zeroes of a bitset + * + * @note Can use C++20 bit manipulation instead, but for now we are in C++17. (https://en.cppreference.com/w/cpp/numeric/countr_zero) + * + * @param bitset The bitset to get the trailing zeroes from + * + * @code{.cpp} + * std::bitset<8> bitset = 0b00001100; + * uint8_t trailing_zeroes = get_trailing_zeroes(bitset); // 2 + * @endcode + * + * @return The number of trailing zeroes + */ + uint8_t get_trailing_zeroes(const std::bitset<8> &bitset) const; + + // Contains the frame data + std::vector zwave_report_frame; + // The first two bytes contains the command class and the command ID + // Those informations are supposed to be valid when we parse the frame. + uint8_t current_index = 2; +}; + +#endif // #ifdef __cplusplus +#endif // #ifndef ZWAVE_FRAME_PARSER_HPP \ No newline at end of file diff --git a/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp b/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp index 26d3e8cf14..6d79cfb663 100644 --- a/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp +++ b/applications/zpc/components/zpc_attribute_store/src/zpc_attribute_store_type_registration.cpp @@ -431,6 +431,75 @@ static const std::vector attribute_schema = { {ATTRIBUTE_COMMAND_CLASS_USER_CODE_SUPPORTED_KEYS, "Supported Keys bitmask", ATTRIBUTE_COMMAND_CLASS_USER_CODE_CAPABILITIES, BYTE_ARRAY_STORAGE_TYPE}, {ATTRIBUTE_COMMAND_CLASS_USER_CODE_CHECKSUM, "User Code Checksum", ATTRIBUTE_COMMAND_CLASS_USER_CODE_DATA, U16_STORAGE_TYPE}, {ATTRIBUTE_COMMAND_CLASS_USER_CODE_KEYPAD_MODE, "Keypad Mode", ATTRIBUTE_COMMAND_CLASS_USER_CODE_DATA, U8_STORAGE_TYPE}, + + + ///////////////////////////////////////////////////////////////////// + // User Credential Command Class attributes + ///////////////////////////////////////////////////////////////////// + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_VERSION, "User Credential Version", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + + // User capabilities + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_NUMBER_OF_USERS, "User Credential User Count", ATTRIBUTE_ENDPOINT_ID, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES, "User Credential Supported Rules", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_MAX_USERNAME_LENGTH, "User Credential Max Username Length", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_USER_SCHEDULE, "User Credential Support User Schedule", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_ALL_USERS_CHECKSUM, "User Credential Support All User Checksum", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_USER_CHECKSUM, "User Credential Support By User Checksum", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_USER_TYPES, "User Credential Supported User types", ATTRIBUTE_ENDPOINT_ID, U32_STORAGE_TYPE}, + + // Credential capabilities + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM, "User Credential Support Credential Checksum", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE, "User Credential Support Credential Admin Code", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION, "User Credential Support Admin Code Deactivation", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, "User Credential Supported Credential Type", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_SUPPORT, "User Credential Learn Support", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SUPPORTED_SLOT_COUNT, "User Credential Supported Slot Count", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MIN_LENGTH, "User Credential Min Length", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MAX_LENGTH, "User Credential Max Length", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT, "User Credential Learn Recommended Timeout", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_NUMBER_OF_STEPS, "User Credential Learn Number Of Steps", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_CHECKSUM, "User Credential Credential Checksum", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_CHECKSUM_MISMATCH_ERROR, "User Credential Credential Checksum Mismatch Error (computed by zpc)", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPE, U16_STORAGE_TYPE}, + + // All Users Checksum + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ALL_USERS_CHECKSUM, "User Credential All User Checksum", ATTRIBUTE_ENDPOINT_ID, U16_STORAGE_TYPE}, + + // User + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, "User Credential User Unique Identifier", ATTRIBUTE_ENDPOINT_ID, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_MODIFIER_TYPE, "User Credential User Modifier Type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_MODIFIER_NODE_ID, "User Credential User Modifier Node ID", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_TYPE, "User Credential User Type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_ACTIVE_STATE, "User Credential User Active State", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_NAME, "User Credential User Name", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, C_STRING_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_NAME_ENCODING, "User Credential User Name Encoding", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_RULE, "User Credential User Credential Rule", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_OPERATION_TYPE, "User Credential User Operation type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_EXPIRING_TIMEOUT_MINUTES, "User Credential User Expiring Timeout Minutes", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_CHECKSUM, "User Credential User Checksum", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_CHECKSUM_MISMATCH_ERROR, "User Credential User Checksum Mismatch Error (computed by zpc)", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U16_STORAGE_TYPE}, + + // Credential + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_TYPE, "User Credential Credential Type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_USER_UNIQUE_ID, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, "User Credential Credential Slot", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_TYPE, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_DATA, "User Credential Credential Data", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, BYTE_ARRAY_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_READ_BACK, "User Credential Credential Read Back Flag", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MODIFIER_TYPE, "User Credential Credential Modifier type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_MODIFIER_NODE_ID, "User Credential Credential Node ID", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_OPERATION_TYPE, "User Credential Credential Operation Type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_OPERATION_TYPE, "User Credential Credential Learn Operation Type", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_TIMEOUT, "User Credential Credential Learn Timeout", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_STATUS, "User Credential Credential Learn Status", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_STEPS_REMAINING, "User Credential Credential Learn Steps Remaining", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ASSOCIATION_DESTINATION_USER_ID, "User Credential Association Destination User ID", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ASSOCIATION_DESTINATION_CREDENTIAL_SLOT, "User Credential Association Destination Credential Slot", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U16_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ASSOCIATION_STATUS, "User Credential Association Status", ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_SLOT, U8_STORAGE_TYPE}, + // Only one learn can be active at the time, so we make this attribute on the endpoint node + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_CREDENTIAL_LEARN_STOP, "User Credential Credential Learn Stop Flag", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + + // Admin + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ADMIN_PIN_CODE, "User Credential Admin Code", ATTRIBUTE_ENDPOINT_ID, BYTE_ARRAY_STORAGE_TYPE}, + {ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_ADMIN_PIN_CODE_OPERATION_RESULT, "User Credential Admin Code Operation Result", ATTRIBUTE_ENDPOINT_ID, U8_STORAGE_TYPE}, + ///////////////////////////////////////////////////////////////////// // Z-Wave Plus Info Command Class attributes ///////////////////////////////////////////////////////////////////// diff --git a/applications/zpc/components/zpc_attribute_store/src/zwave_frame_generator.cpp b/applications/zpc/components/zpc_attribute_store/src/zwave_frame_generator.cpp new file mode 100644 index 0000000000..96c076239a --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/src/zwave_frame_generator.cpp @@ -0,0 +1,190 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Base class +#include "zwave_frame_generator.hpp" + +// Unify +#include "attribute_store_type_registration.h" +#include "sl_log.h" +#include "attribute.hpp" + +// Cpp includes +#include +#include // for ostringstream +#include // for std::for_each + +constexpr char LOG_TAG[] = "zwave_frame_generator"; + +zwave_frame_generator::zwave_frame_generator(uint8_t zwave_command_class) : + current_command_class(zwave_command_class) +{} + +void zwave_frame_generator::initialize_frame(uint8_t zwave_command, + uint8_t *data, + uint16_t data_size) +{ + // Reset current frame index + current_zwave_frame_index = 0; + + // Assignments + current_zwave_frame = data; + current_zwave_frame_size = data_size; + + // Create frame header + add_raw_byte(current_command_class); + add_raw_byte(zwave_command); +} + +void zwave_frame_generator::add_raw_byte(uint8_t byte) +{ + if (current_zwave_frame_index >= current_zwave_frame_size) { + std::ostringstream out; + out << "Attempt to set index " << current_zwave_frame_index + << " when frame size is " << current_zwave_frame_size; + throw std::out_of_range(out.str()); + } + current_zwave_frame[current_zwave_frame_index++] = byte; +} + +std::vector zwave_frame_generator::helper_get_raw_data( + attribute_store_node_t node, + attribute_store_node_value_state_t node_value_state) const +{ + // Used to get the name of the attribute in case of error + const attribute_store::attribute node_cpp(node); + + sl_log_debug(LOG_TAG, node_cpp.value_to_string().c_str()); + + // First get value size + uint8_t value_size = 0; + + // The logic isn't implemented for DESIRED_OR_REPORTED_ATTRIBUTE, so we need to do it + // ourselves. + if (node_value_state == DESIRED_OR_REPORTED_ATTRIBUTE) { + value_size = attribute_store_get_node_value_size(node, DESIRED_ATTRIBUTE); + if (value_size == 0) { + value_size + = attribute_store_get_node_value_size(node, REPORTED_ATTRIBUTE); + } + } else { + value_size = attribute_store_get_node_value_size(node, node_value_state); + } + + if (value_size == 0) { + throw std::runtime_error( + "Failed to get value size from attribute store for attribute " + + node_cpp.name_and_id()); + } + + // Then get raw data + std::vector raw_data; + raw_data.resize(value_size); + sl_status_t status + = attribute_store_get_node_attribute_value(node, + node_value_state, + raw_data.data(), + &value_size); + + if (status != SL_STATUS_OK) { + throw std::runtime_error("Failed to get value for attribute " + + node_cpp.name_and_id()); + } + + return raw_data; +} + +void zwave_frame_generator::add_value( + attribute_store_node_t node, + attribute_store_node_value_state_t node_value_state) +{ + auto raw_data = helper_get_raw_data(node, node_value_state); + + auto storage_type + = attribute_store_get_storage_type(attribute_store_get_node_type(node)); + // Remove the NULL terminator if we are dealing with a string + if (storage_type == C_STRING_STORAGE_TYPE) { + raw_data.pop_back(); + } + + // For non-numeric types we need to send them as is + if (storage_type == C_STRING_STORAGE_TYPE + || storage_type == BYTE_ARRAY_STORAGE_TYPE + || storage_type == FIXED_SIZE_STRUCT_STORAGE_TYPE + || storage_type == INVALID_STORAGE_TYPE) { + // Store in order + std::for_each(raw_data.begin(), raw_data.end(), [this](uint8_t byte) { + add_raw_byte(byte); + }); + } // Otherwise the MSB is always the first in Z-Wave frames (and in attribute store it is last) + else { + // Store in reverse order (reverse iterator to start from the MSB) + std::for_each(raw_data.rbegin(), raw_data.rend(), [this](uint8_t byte) { + add_raw_byte(byte); + }); + } +} + +void zwave_frame_generator::add_shifted_values( + const std::vector &shifted_values) +{ + uint8_t final_value = 0; + for (const auto &shifted_value: shifted_values) { + uint8_t current_value = 0; + // If we don't have a node, take the raw value instead + if (shifted_value.node == ATTRIBUTE_STORE_INVALID_NODE) { + current_value = shifted_value.raw_value; + } else { + auto raw_data = helper_get_raw_data(shifted_value.node, + shifted_value.node_value_state); + if (raw_data.size() != 1) { + throw std::runtime_error("Shifted value should be 1 byte long"); + } + current_value = raw_data[0]; + } + final_value |= (current_value << shifted_value.left_shift); + } + add_raw_byte(final_value); +} + +void zwave_frame_generator::add_shifted_values(const shifted_value &sv) +{ + std::vector shifted_values = {sv}; + add_shifted_values(shifted_values); +} + +void zwave_frame_generator::validate_frame(uint16_t *frame_length) const +{ + if (current_zwave_frame_index == current_zwave_frame_size) { + *frame_length = current_zwave_frame_index; + } else { + std::ostringstream out; + out << "Frame size (" << current_zwave_frame_index + << ") does not match the expected size (" << current_zwave_frame_index + << ")"; + throw std::runtime_error(out.str()); + } +} + +sl_status_t zwave_frame_generator::generate_no_args_frame( + uint8_t zwave_command_id, uint8_t *raw_data, uint16_t *frame_length) +{ + try { + initialize_frame(zwave_command_id, raw_data, 2); + validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, "Failed to generate frame: %s", e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} \ No newline at end of file diff --git a/applications/zpc/components/zpc_attribute_store/src/zwave_frame_parser.cpp b/applications/zpc/components/zpc_attribute_store/src/zwave_frame_parser.cpp new file mode 100644 index 0000000000..03bc1ffc1b --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/src/zwave_frame_parser.cpp @@ -0,0 +1,188 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Base class +#include "zwave_frame_parser.hpp" + +// Unify C +#include "attribute_store_helper.h" + +// Cpp libraries +#include +#include + +#define LOG_TAG "zwave_frame_parser" + +zwave_frame_parser::zwave_frame_parser(const uint8_t *data, uint16_t length) +{ + zwave_report_frame.assign(data, data + length); +} + +bool zwave_frame_parser::is_frame_size_valid(uint8_t min_size, + uint8_t max_size) const +{ + if (max_size == 0) { + max_size = min_size; + } + + uint8_t frame_size = static_cast(zwave_report_frame.size()); + bool frame_valid = (frame_size >= min_size) && (frame_size <= max_size); + + if (!frame_valid) { + if (max_size == min_size) { + sl_log_warning(LOG_TAG, + "Invalid frame size expected %d, got %d", + min_size, + frame_size); + } else { + sl_log_warning(LOG_TAG, + "Invalid frame size expected between %d and %d, got %d", + min_size, + max_size, + frame_size); + } + } + + return frame_valid; +} + +uint8_t zwave_frame_parser::read_byte() +{ + uint8_t value_from_frame = zwave_report_frame.at(current_index); + current_index++; + return value_from_frame; +} + +uint8_t zwave_frame_parser::read_byte(attribute_store_node_t node) +{ + auto value = read_byte(); + + helper_store_value(node, value); + + return value; +} + +zwave_report_bitmask_t zwave_frame_parser::read_bitmask() +{ + constexpr uint8_t SUPPORT_BITMASK_SIZE = sizeof(zwave_report_bitmask_t); + constexpr uint8_t BITMASK_SIZE = SUPPORT_BITMASK_SIZE * 8; + + uint8_t bitmask_length = this->read_byte(); + std::bitset support_bitmask = 0; + + if (bitmask_length > SUPPORT_BITMASK_SIZE) { + throw std::runtime_error( + "zwave_report_bitmask_t supports only bitmask of max size of " + + std::to_string(SUPPORT_BITMASK_SIZE) + " bytes"); + } + + // Implementation node : we don't use sequential read here since for the bitmask the MSB is at the end. + // While standard read in numeric type assume that the MSB is at the beginning. + for (int i = 0; i < bitmask_length; i++) { + std::bitset current_bitmask = this->read_byte(); + support_bitmask |= current_bitmask << (8 * i); + } + + // Convert bitmask into zwave_report_bitmask_t + zwave_report_bitmask_t support_bitmask_value + = static_cast(support_bitmask.to_ulong()); + + return support_bitmask_value; +} + +zwave_report_bitmask_t + zwave_frame_parser::read_bitmask(attribute_store_node_t node) +{ + zwave_report_bitmask_t value = read_bitmask(); + + // Store value if applicable + helper_store_value(node, value); + + return value; +} + +zwave_frame_parser::zwave_parser_bitmask_result + zwave_frame_parser::read_byte_with_bitmask( + const std::vector &bitmask_data) +{ + zwave_frame_parser::zwave_parser_bitmask_result read_values; + + if (!bitmask_data.empty()) { + uint8_t value_from_frame = read_byte(); + + for (const auto ¤t_bitmask: bitmask_data) { + // Extract value + uint8_t current_value = current_bitmask.bitmask & value_from_frame; + // Compute shift to get the actual value (e.g if we want bit 3 & 4 both at 1 we want to store 0b11 not 0b1100) + uint8_t shift = get_trailing_zeroes(current_bitmask.bitmask); + current_value >>= shift; + + read_values.insert({current_bitmask.bitmask, current_value}); + + // Guard to avoid printing error message + if (attribute_store_node_exists(current_bitmask.destination_node)) { + helper_store_value(current_bitmask.destination_node, current_value); + } + } + } + return read_values; +} + +zwave_frame_parser::zwave_parser_bitmask_result + zwave_frame_parser::read_byte_with_bitmask(const bitmask_data &data) +{ + std::vector bitmask_data {data}; + return read_byte_with_bitmask(bitmask_data); +} + +std::string zwave_frame_parser::read_string() +{ + uint8_t string_length = read_byte(); + + return read_sequential(string_length); +} + +std::string zwave_frame_parser::read_string(attribute_store_node_t node) +{ + std::string value = read_string(); + + helper_store_value(node, value); + + return value; +} + +// Can use C++20 bit manipulation instead, but for now we are in C++17. +// https://en.cppreference.com/w/cpp/numeric/countr_zero +uint8_t + zwave_frame_parser::get_trailing_zeroes(const std::bitset<8> &bitset) const +{ + std::bitset<8> temp_bitset = bitset; + uint8_t trailing_zeroes = 0; + + if (temp_bitset.any()) { + /* mask the 4 low order bits, add 4 and shift them out if they are all 0 */ + if ((temp_bitset & std::bitset<8>(0xF)).none()) { + trailing_zeroes += 4; + temp_bitset >>= 4; + } + /* mask the 2 low order bits, add 2 and shift them out if they are all 0 */ + if ((temp_bitset & std::bitset<8>(0x3)).none()) { + trailing_zeroes += 2; + temp_bitset >>= 2; + } + /* mask the low order bit and add 1 if it is 0 */ + if ((temp_bitset & std::bitset<8>(0x1)).none()) { + trailing_zeroes += 1; + } + } + return trailing_zeroes; +} \ No newline at end of file diff --git a/applications/zpc/components/zpc_attribute_store/test/CMakeLists.txt b/applications/zpc/components/zpc_attribute_store/test/CMakeLists.txt index 227f39b068..815f8aaab5 100644 --- a/applications/zpc/components/zpc_attribute_store/test/CMakeLists.txt +++ b/applications/zpc/components/zpc_attribute_store/test/CMakeLists.txt @@ -56,3 +56,23 @@ target_add_unittest( DEPENDS zpc_attribute_store_test_helper zwave_network_management_mock) + +# Frame Parser test +target_add_unittest( + zpc_attribute_store + NAME + zwave_frame_parser_test + SOURCES + zwave_frame_parser_test.cpp + DEPENDS + zpc_attribute_store_test_helper) + +# Frame Generator test +target_add_unittest( + zpc_attribute_store + NAME + zwave_frame_generator_test + SOURCES + zwave_frame_generator_test.cpp + DEPENDS + zpc_attribute_store_test_helper) diff --git a/applications/zpc/components/zpc_attribute_store/test/zwave_frame_generator_test.cpp b/applications/zpc/components/zpc_attribute_store/test/zwave_frame_generator_test.cpp new file mode 100644 index 0000000000..be94655ec3 --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/test/zwave_frame_generator_test.cpp @@ -0,0 +1,371 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Test lib +#include "unity.h" + +// Tested class +#include "zwave_frame_generator.hpp" + +// Attribute store +#include "attribute_store_defined_attribute_types.h" +#include "zpc_attribute_store_type_registration.h" +#include "attribute_store_fixt.h" +#include "datastore_fixt.h" +#include "attribute.hpp" + +// Test Helper +#include "zpc_attribute_store_test_helper.h" + +extern "C" { + +//////////////////////////////////////////////////////////////////////// +// Static variables +//////////////////////////////////////////////////////////////////////// +// Value does not matter, we are only testing the frame generation +static const uint8_t MAIN_COMMAND_CLASS = COMMAND_CLASS_SWITCH_BINARY; +static const uint8_t MAIN_COMMAND_ID = 0x12; + +// Frame generator static init, we don't have to create it for every tests +static zwave_frame_generator frame_generator(MAIN_COMMAND_CLASS); +static attribute_store::attribute endpoint_id_node_cpp; + +//////////////////////////////////////////////////////////////////////// +// Helper class +//////////////////////////////////////////////////////////////////////// +class helper_test_generated_frame +{ + public: + helper_test_generated_frame(zwave_frame_generator &frame_generator) : + frame_generator(frame_generator) + {} + + void initialize_frame(const std::vector &expected_tested_frame, + uint8_t command_id = MAIN_COMMAND_ID) + { + expected_frame = expected_tested_frame; + + generated_frame.clear(); + generated_frame.resize(expected_frame.size()); + + frame_generator.initialize_frame(command_id, + generated_frame.data(), + generated_frame.size()); + } + + void validate_generated_frame() + { + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected_frame.data(), + generated_frame.data(), + generated_frame.size(), + "Frame mismatch"); + + uint16_t reported_size = 0; + frame_generator.validate_frame(&reported_size); + TEST_ASSERT_EQUAL_MESSAGE(expected_frame.size(), + reported_size, + "Frame size mismatch"); + } + + private: + zwave_frame_generator &frame_generator; + + std::vector generated_frame; + std::vector expected_frame; +}; + +static helper_test_generated_frame helper_test_frame(frame_generator); + +/// Setup the test suite (called once before all test_xxx functions are called) +void suiteSetUp() +{ + datastore_fixt_setup(":memory:"); + attribute_store_init(); + zpc_attribute_store_register_known_attribute_types(); +} + +/// Teardown the test suite (called once after all test_xxx functions are called) +int suiteTearDown(int num_failures) +{ + datastore_fixt_teardown(); + return num_failures; +} + +/// Called before each and every test +void setUp() +{ + zpc_attribute_store_test_helper_create_network(); + endpoint_id_node_cpp = attribute_store::attribute(endpoint_id_node); +} + +#define TEST_ASSERT_EXCEPTION_MESSAGE(f, msg) \ + try { \ + f; \ + TEST_FAIL_MESSAGE(msg); \ + } catch (...) { \ + }; + +//////////////////////////////////////////////////////////////////////// +// Helper functions +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +// Test functions +//////////////////////////////////////////////////////////////////////// +void test_zwave_frame_generator_add_raw_value_happy_case() +{ + // First test with a single byte + uint8_t command_id + = MAIN_COMMAND_ID; // Value does not matter, we are only testing the frame generation + uint8_t tested_value = 12; + uint8_t tested_value_2 = 127; + + // Create & test frame 1 + std::vector expected_frame + = {MAIN_COMMAND_CLASS, command_id, tested_value}; + + helper_test_frame.initialize_frame(expected_frame); + frame_generator.add_raw_byte(tested_value); + + helper_test_frame.validate_generated_frame(); + + // Second test with a multiples byte + command_id = 0x13; + tested_value = 15; + // Create frame 2 + expected_frame + = {MAIN_COMMAND_CLASS, command_id, tested_value, tested_value_2}; + + helper_test_frame.initialize_frame(expected_frame, command_id); + frame_generator.add_raw_byte(tested_value); + frame_generator.add_raw_byte(tested_value_2); + + helper_test_frame.validate_generated_frame(); +} + +void test_zwave_frame_generator_add_value_happy_case() +{ + // Setup attribute store + uint8_t uint8_value = 12; + auto uint8_node = endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_VERSION); + uint8_node.set_reported(uint8_value); + + uint16_t uint16_value = 1212; + auto uint16_node = endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_NODE_ID); + uint16_node.set_desired(uint16_value); + + std::string string_value = "DoUzE"; + auto string_node = endpoint_id_node_cpp.add_node(ATTRIBUTE_NODE_NAME); + string_node.set_desired(string_value); + + std::vector raw_data = {112, 113, 114}; + auto raw_data_node = endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_SENSOR_MULTILEVEL_SUPPORTED_SENSOR_TYPES); + raw_data_node.set_reported(raw_data); + + // Create the expected frame + // Test the frame + std::vector expected_frame + = {MAIN_COMMAND_CLASS, MAIN_COMMAND_ID, uint8_value}; + // Uint16 + // MSB + expected_frame.push_back((uint16_value & 0xFF00) >> 8); + // LSB + expected_frame.push_back((uint16_value & 0x00FF)); + // String + for (auto c: string_value) { + expected_frame.push_back(static_cast(c)); + } + // Raw data + for (auto c: raw_data) { + expected_frame.push_back(c); + } + + // Generate the frame + helper_test_frame.initialize_frame(expected_frame); + frame_generator.add_value(uint8_node, DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(uint16_node, DESIRED_ATTRIBUTE); + frame_generator.add_value(string_node, DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(raw_data_node); + + helper_test_frame.validate_generated_frame(); +} + +void test_zwave_frame_generator_add_value_invalid_node() +{ + std::vector frame; + uint16_t expected_size = 3; + frame.resize(expected_size); + + // Generate the frame + frame_generator.initialize_frame(MAIN_COMMAND_ID, + frame.data(), + expected_size); + + // Test with an invalid node + TEST_ASSERT_EXCEPTION_MESSAGE( + frame_generator.add_value(ATTRIBUTE_STORE_INVALID_NODE), + "Invalid node should throw an exception"); +} + +void test_zwave_frame_generator_raw_shifted_value_happy_case() +{ + // Create expected frame + std::vector expected_frame + = {MAIN_COMMAND_CLASS, MAIN_COMMAND_ID, 0b1100, 0b101100}; + + std::vector values = { + {.left_shift = 2, .raw_value = 0b11}, // 0000 1100 + {.left_shift = 5, .raw_value = 0b1}, // 0010 0000 + }; + + helper_test_frame.initialize_frame(expected_frame); + frame_generator.add_shifted_values(values[0]); // Should be 0b1100 + frame_generator.add_shifted_values(values); // Should be 0b101100 + + helper_test_frame.validate_generated_frame(); +} + +void test_zwave_frame_generator_node_shifted_value_happy_case() +{ + const std::vector shift_values = {0, 3, 6}; + const std::vector node_values = {0b11, 0b1, 0b11}; + const std::vector node_value_states + = {REPORTED_ATTRIBUTE, DESIRED_ATTRIBUTE, DESIRED_OR_REPORTED_ATTRIBUTE}; + + std::vector attributes; + std::vector values; + + TEST_ASSERT_TRUE_MESSAGE( + node_values.size() == node_value_states.size() + && node_values.size() == shift_values.size(), + "Node values and node value states should have the same size"); + + for (size_t i = 0; i < node_values.size(); i++) { + auto current_cpp_node = endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_VERSION); + + attributes.push_back(current_cpp_node); + + auto current_state = node_value_states[i]; + current_state = current_state == DESIRED_OR_REPORTED_ATTRIBUTE + ? DESIRED_ATTRIBUTE + : current_state; + auto current_value = node_values[i]; + + current_cpp_node.set(current_state, current_value); + + values.push_back({.left_shift = shift_values[i], + .node = current_cpp_node, + .node_value_state = current_state}); + } + + std::vector values_mix = { + {.left_shift = 2, + .node = attributes[0], + .node_value_state = node_value_states[0]}, + {.left_shift = 7, .raw_value = 0b1}, + }; + + // Create expected frame + std::vector expected_frame + = {MAIN_COMMAND_CLASS, MAIN_COMMAND_ID, 0b11001011, 0b10001100}; + + // Generate the frame + helper_test_frame.initialize_frame(expected_frame); + frame_generator.add_shifted_values(values); // Should be 0b11001011 + frame_generator.add_shifted_values(values_mix); // Should be 0b10001100 + + helper_test_frame.validate_generated_frame(); +} + +void test_zwave_frame_generator_node_shifted_value_invalid_node() +{ + std::vector frame; + uint16_t expected_size = 3; + frame.resize(expected_size); + + // Node 1212 should exists here + zwave_frame_generator::shifted_value value = {.left_shift = 2, .node = 1212}; + // Generate the frame + frame_generator.initialize_frame(MAIN_COMMAND_ID, + frame.data(), + expected_size); + + // Test with an invalid node + TEST_ASSERT_EXCEPTION_MESSAGE(frame_generator.add_shifted_values(value), + "Invalid node ID should throw an exception"); +} + +void test_zwave_frame_generator_out_of_bounds() +{ + std::vector frame; + uint16_t expected_size = 2; + frame.resize(expected_size); + + // Node 1212 should exists here + zwave_frame_generator::shifted_value value + = {.left_shift = 2, .raw_value = 12}; + // Generate the frame + frame_generator.initialize_frame(MAIN_COMMAND_ID, + frame.data(), + expected_size); + + // Test with shifted value + TEST_ASSERT_EXCEPTION_MESSAGE( + frame_generator.add_shifted_values(value), + "Out of bound write should throw an exception for add_shifted_values"); + + // Test raw byte + TEST_ASSERT_EXCEPTION_MESSAGE( + frame_generator.add_raw_byte(12), + "Out of bound write should throw an exception for add_raw_byte"); + + uint16_t uint16_value = 1212; + auto uint16_node = endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_NODE_ID); + uint16_node.set_reported(uint16_value); + // Test raw byte + TEST_ASSERT_EXCEPTION_MESSAGE( + frame_generator.add_value(uint16_node), + "Out of bound write should throw an exception for add_value"); +} + +void test_zwave_frame_generator_generate_no_args_frame() +{ + // Create expected frame + std::vector expected_frame = {MAIN_COMMAND_CLASS, MAIN_COMMAND_ID}; + + std::vector generated_frame; + generated_frame.resize(expected_frame.size()); + + uint16_t frame_length = 0; + sl_status_t status + = frame_generator.generate_no_args_frame(MAIN_COMMAND_ID, + generated_frame.data(), + &frame_length); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, status, "Failed to generate frame"); + + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected_frame.data(), + generated_frame.data(), + generated_frame.size(), + "Frame mismatch"); + + TEST_ASSERT_EQUAL_MESSAGE(expected_frame.size(), + frame_length, + "Frame size mismatch"); +} + +} // extern "C" \ No newline at end of file diff --git a/applications/zpc/components/zpc_attribute_store/test/zwave_frame_parser_test.cpp b/applications/zpc/components/zpc_attribute_store/test/zwave_frame_parser_test.cpp new file mode 100644 index 0000000000..c8561c793b --- /dev/null +++ b/applications/zpc/components/zpc_attribute_store/test/zwave_frame_parser_test.cpp @@ -0,0 +1,631 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Test lib +#include "unity.h" + +// Tested class +#include "zwave_frame_parser.hpp" + +// Attribute store +#include "zpc_attribute_store_all_ids.h" +#include "zpc_attribute_store_type_registration.h" +#include "attribute_store_fixt.h" +#include "datastore_fixt.h" +#include "attribute.hpp" + +// Test Helper +#include "zpc_attribute_store_test_helper.h" + +extern "C" { + +/// Setup the test suite (called once before all test_xxx functions are called) +void suiteSetUp() +{ + datastore_fixt_setup(":memory:"); + attribute_store_init(); + zpc_attribute_store_register_known_attribute_types(); +} + +/// Teardown the test suite (called once after all test_xxx functions are called) +int suiteTearDown(int num_failures) +{ + datastore_fixt_teardown(); + return num_failures; +} + +/// Called before each and every test +void setUp() +{ + zpc_attribute_store_test_helper_create_network(); +} + +#define TEST_ASSERT_EXCEPTION_MESSAGE(f, msg) \ + try { \ + f; \ + TEST_FAIL_MESSAGE(msg); \ + } catch (...) { \ + }; + +void test_is_frame_size_valid() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_TRUE_MESSAGE(parser.is_frame_size_valid(expected_frame_size), + "Frame size should be valid"); + TEST_ASSERT_FALSE_MESSAGE(parser.is_frame_size_valid(expected_frame_size + 1), + "Frame size shouldn't be valid"); +} + +void test_read_happy_case() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0x03, 0x04}; + // In this test we perform 2 read and then test if it goes + // out of bounds so we need it to be strictly equal to 4 + uint8_t expected_frame_size = 4; + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_TRUE_MESSAGE(parser.is_frame_size_valid(expected_frame_size), + "Frame size should be valid"); + + uint8_t value = parser.read_byte(); + TEST_ASSERT_EQUAL_MESSAGE( + tested_frame[2], + value, + "First read should return the 3rd byte of the frame"); + + // We need an attribute that is registered as uint8_t + auto tested_node + = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_VERSION, + endpoint_id_node); + + value = parser.read_byte(tested_node); + TEST_ASSERT_EQUAL_MESSAGE( + tested_frame[3], + value, + "Second read should return the 4th byte of the frame"); + + attribute_store::attribute cpp_tested_node(tested_node); + TEST_ASSERT_EQUAL_MESSAGE(tested_frame[3], + cpp_tested_node.get(REPORTED_ATTRIBUTE), + "Tested node should have the same reported value " + "as the 4th byte of the frame"); +} + +// This function will assume that the parser have those values inside : +// +// Frame start +// // expected_int8_value +// 0x0F +// // expected_int16_value +// 0x0F +// 0xFF +// // expected_int32_value +// 0x0F +// 0xFF +// 0xFF +// 0xFF +// Frame end +void helper_test_signed_value(zwave_frame_parser &parser, + int8_t expected_int8_value, + int16_t expected_int16_value, + int32_t expected_int32_value) +{ + // Any Int32 value will do the trick here + attribute_store::attribute int32_node + = attribute_store_add_node(ATTRIBUTE_MANUFACTURER_SPECIFIC_MANUFACTURER_ID, + endpoint_id_node); + + // 8 bits + int8_t returned_int8_value = parser.read_sequential(1, int32_node); + TEST_ASSERT_EQUAL_MESSAGE(expected_int8_value, + returned_int8_value, + "Returned value mismatch for 8 bit signed value"); + // We need to test the reported value of a int32_t and not cast it to see if value matches + TEST_ASSERT_EQUAL_MESSAGE( + expected_int8_value, + int32_node.reported(), + "Node reported value mismatch for 8 bit signed value"); + + // 16 bits + int16_t returned_int16_value = parser.read_sequential(2, int32_node); + TEST_ASSERT_EQUAL_MESSAGE(expected_int16_value, + returned_int16_value, + "Returned value mismatch for 16 bit signed value"); + // We need to test the reported value of a int32_t and not cast it to see if value matches + TEST_ASSERT_EQUAL_MESSAGE( + expected_int16_value, + int32_node.reported(), + "Node reported value mismatch for 16 bit signed value"); + + // 16 bits + int32_t returned_int32_value = parser.read_sequential(4, int32_node); + TEST_ASSERT_EQUAL_MESSAGE(expected_int32_value, + returned_int32_value, + "Returned value mismatch for 32 bit signed value"); + // We need to test the reported value of a int32_t and not cast it to see if value matches + TEST_ASSERT_EQUAL_MESSAGE( + expected_int32_value, + int32_node.reported(), + "Node reported value mismatch for 32 bit signed value"); +} + +void test_read_signed_negative_values_happy_case() +{ + const uint8_t tested_frame[] = {0x01, + 0x02, + // Signed 8 bit value (negative) + 0xF4, + // Signed 16 bit value (negative) + 0xFB, + 0x44, + // Signed 32 bit value(negative) + 0xFF, + 0xFE, + 0x26, + 0x84}; + + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_TRUE_MESSAGE(parser.is_frame_size_valid(expected_frame_size), + "Frame size should be valid"); + + helper_test_signed_value(parser, -12, -1212, -121212); +} + +void test_read_signed_positive_values_happy_case() +{ + const uint8_t tested_frame[] = {0x01, + 0x02, + // Signed 8 bit value (positive) + 0x0C, + // Signed 16 bit value (positive) + 0x04, + 0xBC, + // Signed 32 bit value(positive) + 0x00, + 0x01, + 0xD9, + 0x7C}; + + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_TRUE_MESSAGE(parser.is_frame_size_valid(expected_frame_size), + "Frame size should be valid"); + + helper_test_signed_value(parser, 12, 1212, 121212); +} + +void test_read_signed_values_incompatible_size() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0x0C, 0x04, 0xBC}; + + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_TRUE_MESSAGE(parser.is_frame_size_valid(expected_frame_size), + "Frame size should be valid"); + + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_sequential(3), + "Should throw an exception when trying to read incompatible size"); +} + +void test_read_out_of_bounds() +{ + const uint8_t tested_frame[] = {0x01, 0x02}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_byte(), + "Should throw an exception when trying to read out of bounds"); + + auto tested_node + = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_VERSION, + endpoint_id_node); + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_byte(tested_node), + "Should throw an exception when trying to read out of bounds"); +} + +struct read_sequential_nodes { + attribute_store::attribute uint8_node = {ATTRIBUTE_STORE_INVALID_NODE}; + attribute_store::attribute uint16_node = {ATTRIBUTE_STORE_INVALID_NODE}; + attribute_store::attribute uint32_node = {ATTRIBUTE_STORE_INVALID_NODE}; + attribute_store::attribute byte_array_node = {ATTRIBUTE_STORE_INVALID_NODE}; + attribute_store::attribute c_string_node = {ATTRIBUTE_STORE_INVALID_NODE}; +}; + +void helper_test_read_sequential_happy_case(read_sequential_nodes nodes = {}) +{ + const uint8_t tested_frame[] = {0x00, + 0x00, + // Read 1 byte + 0x12, + // Read 2 bytes + 0x34, + 0x56, + // Read 4 bytes + 0x78, + 0x9A, + 0xBC, + 0xDE, + // Vector read 3 bytes, + 0xF0, + 0x00, + 0x0F, + // String read (DoUzE) + 0x44, + 0x6F, + 0x55, + 0x7A, + 0x45}; + + uint8_t expected_frame_size = sizeof(tested_frame); + + // Init parser + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // uint8_t + uint8_t tested_uint8_value = tested_frame[2]; + TEST_ASSERT_EQUAL_MESSAGE( + tested_uint8_value, + parser.read_sequential(1, nodes.uint8_node), + "Should be able to read 1 byte from frame"); + + if (nodes.uint8_node != ATTRIBUTE_STORE_INVALID_NODE) { + TEST_ASSERT_EQUAL_MESSAGE(tested_uint8_value, + nodes.uint8_node.get(REPORTED_ATTRIBUTE), + "Invalid uint8_t value in attribute store"); + } + + // uint16_t + uint16_t tested_uint16_value = tested_frame[3] << 8 | tested_frame[4]; + TEST_ASSERT_EQUAL_MESSAGE( + tested_uint16_value, + parser.read_sequential(2, nodes.uint16_node), + "Should be able to read 2 bytes from frame"); + if (nodes.uint16_node != ATTRIBUTE_STORE_INVALID_NODE) { + TEST_ASSERT_EQUAL_MESSAGE( + tested_uint16_value, + nodes.uint16_node.get(REPORTED_ATTRIBUTE), + "Invalid uint16_t value in attribute store"); + } + + // uint32_t + uint32_t tested_uint32_value = tested_frame[5] << 24 | tested_frame[6] << 16 + | tested_frame[7] << 8 | tested_frame[8]; + TEST_ASSERT_EQUAL_MESSAGE( + tested_uint32_value, + parser.read_sequential(4, nodes.uint32_node), + "Should be able to read 4 bytes from frame"); + + if (nodes.uint32_node != ATTRIBUTE_STORE_INVALID_NODE) { + TEST_ASSERT_EQUAL_MESSAGE( + tested_uint32_value, + nodes.uint32_node.get(REPORTED_ATTRIBUTE), + "Invalid uint32_t value in attribute store"); + } + + // uint8_t vector + std::vector tested_vector_value = {0xF0, 0x00, 0x0F}; + std::vector reported_vector_value + = parser.read_sequential>(3, nodes.byte_array_node); + + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE( + tested_vector_value.data(), + reported_vector_value.data(), + tested_vector_value.size(), + "Should be able to read 3 bytes from frame"); + + if (nodes.byte_array_node != ATTRIBUTE_STORE_INVALID_NODE) { + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE( + tested_vector_value.data(), + nodes.byte_array_node.get>(REPORTED_ATTRIBUTE) + .data(), + tested_vector_value.size(), + "Invalid uint8_t array value in attribute store"); + } + + // String + const char *tested_string_value = "DoUzE"; + TEST_ASSERT_EQUAL_STRING_MESSAGE( + tested_string_value, + parser.read_sequential(5, nodes.c_string_node).c_str(), + "Should be able to read 5 bytes from frame"); + + if (nodes.c_string_node != ATTRIBUTE_STORE_INVALID_NODE) { + TEST_ASSERT_EQUAL_STRING_MESSAGE( + tested_string_value, + nodes.c_string_node.get(REPORTED_ATTRIBUTE).c_str(), + "Invalid c string value in attribute store"); + } + + // Test exception + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_sequential(1), + "Should throw an exception when trying to read out of bounds"); +} + +void test_read_sequential_no_attributes_happy_case() +{ + helper_test_read_sequential_happy_case(); +} +void test_read_sequential_with_attributes_happy_case() +{ + // Any nodes that have the right type and under endpoint_id will do the trick here + read_sequential_nodes data = { + .uint8_node + = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_VERSION, + endpoint_id_node), + .uint16_node = attribute_store_add_node( + ATTRIBUTE_COMMAND_CLASS_CONFIGURATION_NEXT_SUPPORTED_PARAMETER_ID, + endpoint_id_node), + .uint32_node = attribute_store_add_node( + ATTRIBUTE_COMMAND_CLASS_CENTRAL_SCENE_ACTIVE_SCENE, + endpoint_id_node), + .byte_array_node + = attribute_store_add_node(ATTRIBUTE_COMMAND_CLASS_METER_SUPPORTED_SCALES, + endpoint_id_node), + .c_string_node + = attribute_store_add_node(ATTRIBUTE_NODE_NAME, endpoint_id_node), + }; + + helper_test_read_sequential_happy_case(data); +} + +void test_read_sequential_out_of_bounds_int() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0x03}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_sequential(2), + "Should throw an exception when trying to read out of bounds"); +} + +void test_read_sequential_out_of_bounds_vector() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0x03}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_sequential>(2), + "Should throw an exception when trying to read out of bounds"); +} + +void test_read_sequential_out_of_bounds_string() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0x03}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_EXCEPTION_MESSAGE( + parser.read_sequential(2), + "Should throw an exception when trying to read out of bounds"); +} + +void test_read_byte_with_bitmask_no_attribute_happy_case() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0b00001110, 0b10100111}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Read first value + constexpr uint8_t BITMASK_SINGLE = 0b00000011; + zwave_frame_parser::bitmask_data single_bitmask = {.bitmask = BITMASK_SINGLE}; + zwave_frame_parser::zwave_parser_bitmask_result reported_values + = parser.read_byte_with_bitmask(single_bitmask); + zwave_frame_parser::zwave_parser_bitmask_result tested_reported_values + = {{BITMASK_SINGLE, 0b10}}; + + TEST_ASSERT_TRUE_MESSAGE( + reported_values == tested_reported_values, + "Should be able to read first value with only one bitmask"); + + // Read second value + constexpr uint8_t BITMASK_MULTIPLE_A = 0b11000000; + constexpr uint8_t BITMASK_MULTIPLE_B = 0b00111000; + constexpr uint8_t BITMASK_MULTIPLE_C = 0b00000011; + + reported_values + = parser.read_byte_with_bitmask({{.bitmask = BITMASK_MULTIPLE_A}, + {.bitmask = BITMASK_MULTIPLE_B}, + {.bitmask = BITMASK_MULTIPLE_C}}); + tested_reported_values = {{BITMASK_MULTIPLE_A, 0b10}, + {BITMASK_MULTIPLE_B, 0b100}, + {BITMASK_MULTIPLE_C, 0b11}}; + + TEST_ASSERT_TRUE_MESSAGE( + reported_values == tested_reported_values, + "Should be able to read bitmask value with 3 bitmasks"); +} + +void test_read_byte_with_bitmask_with_attribute_happy_case() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 0b00001110, 0b10100111}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Any nodes that have the right type (uint8_t) and under endpoint_id will do the trick here + attribute_store::attribute endpoint_id_node_cpp(endpoint_id_node); + std::vector tested_nodes = { + endpoint_id_node_cpp.add_node(ATTRIBUTE_COMMAND_CLASS_ALARM_SENSOR_VERSION), + endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_BARRIER_OPERATOR_VERSION), + endpoint_id_node_cpp.add_node(ATTRIBUTE_COMMAND_CLASS_SWITCH_COLOR_VERSION), + endpoint_id_node_cpp.add_node(ATTRIBUTE_COMMAND_CLASS_BASIC_VERSION)}; + + // Read first value + constexpr uint8_t BITMASK_SINGLE = 0b00000011; + zwave_frame_parser::bitmask_data single_bitmask + = {.bitmask = BITMASK_SINGLE, .destination_node = tested_nodes[0]}; + zwave_frame_parser::zwave_parser_bitmask_result reported_values + = parser.read_byte_with_bitmask(single_bitmask); + zwave_frame_parser::zwave_parser_bitmask_result tested_reported_values + = {{BITMASK_SINGLE, 0b10}}; + + TEST_ASSERT_TRUE_MESSAGE( + reported_values == tested_reported_values, + "Should be able to read first value with only one bitmask"); + + TEST_ASSERT_EQUAL_MESSAGE(tested_reported_values[BITMASK_SINGLE], + tested_nodes[0].get(REPORTED_ATTRIBUTE), + "Value on node_1 should match the returned value"); + + // Read second value + constexpr uint8_t BITMASK_MULTIPLE_A = 0b11000000; + constexpr uint8_t BITMASK_MULTIPLE_B = 0b00111000; + constexpr uint8_t BITMASK_MULTIPLE_C = 0b00000011; + std::vector data + = {{.bitmask = BITMASK_MULTIPLE_A, .destination_node = tested_nodes[1]}, + {.bitmask = BITMASK_MULTIPLE_B, .destination_node = tested_nodes[2]}, + {.bitmask = BITMASK_MULTIPLE_C, .destination_node = tested_nodes[3]}}; + reported_values = parser.read_byte_with_bitmask(data); + + tested_reported_values = {{BITMASK_MULTIPLE_A, 0b10}, + {BITMASK_MULTIPLE_B, 0b100}, + {BITMASK_MULTIPLE_C, 0b11}}; + + TEST_ASSERT_TRUE_MESSAGE( + reported_values == tested_reported_values, + "Should be able to read bitmask value with 3 bitmasks"); + + TEST_ASSERT_EQUAL_MESSAGE( + tested_reported_values[BITMASK_MULTIPLE_A], + tested_nodes[1].get(REPORTED_ATTRIBUTE), + "Value on node should match the returned value (tested_nodes[1])"); + TEST_ASSERT_EQUAL_MESSAGE( + tested_reported_values[BITMASK_MULTIPLE_B], + tested_nodes[2].get(REPORTED_ATTRIBUTE), + "Value on node should match the returned value (tested_nodes[2])"); + TEST_ASSERT_EQUAL_MESSAGE( + tested_reported_values[BITMASK_MULTIPLE_C], + tested_nodes[3].get(REPORTED_ATTRIBUTE), + "Value on node should match the returned value (tested_nodes[3])"); +} + +void test_read_bitmask_no_attribute_happy_case() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 2, 0xFF, 0x02}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Read first value + zwave_report_bitmask_t reported_value = parser.read_bitmask(); + zwave_report_bitmask_t tested_value = 0x02FF; + + TEST_ASSERT_EQUAL_MESSAGE(tested_value, + reported_value, + "Should be able to read support bitmask value"); +} + +void test_read_bitmask_attribute_happy_case() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 3, 0x12, 0xFF, 0x02}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Any nodes that have the right type (zwave_report_bitmask_t) and under endpoint_id will do the trick here + attribute_store::attribute endpoint_id_node_cpp(endpoint_id_node); + auto bitmask_node = endpoint_id_node_cpp.add_node( + ATTRIBUTE_COMMAND_CLASS_THERMOSTAT_SUPPORTED_MODES); + + // Read first value + zwave_report_bitmask_t reported_value = parser.read_bitmask(bitmask_node); + zwave_report_bitmask_t tested_value = 0x02FF12; + + TEST_ASSERT_EQUAL_MESSAGE(tested_value, + reported_value, + "Should be able to read support bitmask value"); + + TEST_ASSERT_EQUAL_MESSAGE( + tested_value, + bitmask_node.get(REPORTED_ATTRIBUTE), + "Value on node should match the returned value"); +} + +void test_read_bitmask_value_too_big() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + uint8_t expected_frame_size = sizeof(tested_frame); + zwave_frame_parser parser(tested_frame, expected_frame_size); + + TEST_ASSERT_EXCEPTION_MESSAGE(parser.read_bitmask(), + "Should throw an exception when trying to read " + "a support bitmask value that is too big"); +} + +void test_read_string_no_attribute_happy_case() +{ + const uint8_t tested_frame[] = {0x01, 0x02, 5, 'D', 'o', 'U', 'z', 'E'}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Read first value + std::string reported_value = parser.read_string(); + const char *tested_value = "DoUzE"; + + TEST_ASSERT_EQUAL_STRING_MESSAGE(tested_value, + reported_value.c_str(), + "Should be able to read string value"); +} + +void test_read_string_with_attribute_happy_case() +{ + const uint8_t tested_frame[] + = {0x01, 0x02, 10, 'C', 'H', 'O', 'K', 'B', 'A', 'R', '2', 'B', 'Z'}; + uint8_t expected_frame_size = sizeof(tested_frame); + + zwave_frame_parser parser(tested_frame, expected_frame_size); + + // Any nodes that have the right type (zwave_report_bitmask_t) and under endpoint_id will do the trick here + attribute_store::attribute endpoint_id_node_cpp(endpoint_id_node); + auto string_node = endpoint_id_node_cpp.add_node(ATTRIBUTE_NODE_NAME); + + // Read first value + std::string reported_value = parser.read_string(string_node); + const char *tested_value = "CHOKBAR2BZ"; + + TEST_ASSERT_EQUAL_STRING_MESSAGE(tested_value, + reported_value.c_str(), + "Should be able to read string value"); + + TEST_ASSERT_EQUAL_STRING_MESSAGE( + tested_value, + string_node.get(REPORTED_ATTRIBUTE).c_str(), + "Value on node should match the returned value"); +} + +} // extern "C" diff --git a/applications/zpc/components/zwave_command_classes/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/CMakeLists.txt index 5594af72e8..cbe37198d8 100644 --- a/applications/zpc/components/zwave_command_classes/CMakeLists.txt +++ b/applications/zpc/components/zwave_command_classes/CMakeLists.txt @@ -54,13 +54,23 @@ add_library( src/zwave_command_class_thermostat_operating_state.c src/zwave_command_class_time.c src/zwave_command_class_user_code.c + src/zwave_command_class_user_credential.cpp + src/zwave_command_class_user_credential_api.cpp + src/zwave_command_class_version.c src/zwave_command_class_wake_up.c src/zwave_command_class_zwave_plus_info.c src/zwave_command_classes_fixt.c src/zwave_command_classes_utils.c src/zwave_command_class_inclusion_controller.cpp - src/zwave_command_class_transport_service.c) + src/zwave_command_class_transport_service.c + + src/private/user_credential/user_credential_user_capabilities.cpp + src/private/user_credential/user_credential_credential_capabilities.cpp + src/private/user_credential/user_credential_credential_type_capabilities.cpp + src/private/user_credential/user_credential_checksum_calculator.cpp + src/private/user_credential/user_credential_helpers.cpp + ) install(TARGETS zwave_command_classes LIBRARY DESTINATION lib) target_include_directories( @@ -131,6 +141,9 @@ if(BUILD_TESTING) # Mocks target_add_mock(zwave_command_classes) + add_mock(zwave_command_class_notification_mock src/zwave_command_class_notification.h) + target_interface_libraries(zwave_command_class_notification_mock zpc_utils zwave_command_handler) + # Unit test subdirectory add_subdirectory(test) endif() diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_checksum_calculator.cpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_checksum_calculator.cpp new file mode 100644 index 0000000000..f272038f8b --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_checksum_calculator.cpp @@ -0,0 +1,106 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Base class +#include "user_credential_checksum_calculator.h" + +// CRC 16 +#include "zwave_controller_crc16.h" + +// Common definitions +#include "user_credential_definitions.hpp" + +namespace user_credential +{ + +// Used to compute checksums +constexpr uint16_t CRC_INITIALIZATION_VALUE = 0x1D0F; +constexpr uint8_t MAX_CHAR_SIZE = 64; + +std::vector + get_raw_data_from_node(const attribute_store::attribute &node) +{ + std::vector raw_data; + auto value_size + = attribute_store_get_node_value_size(node, REPORTED_ATTRIBUTE); + + if (value_size == 0) { + throw std::runtime_error( + "Failed to get value size from attribute store for attribute " + + node.name_and_id()); + } + + raw_data.resize(value_size); + sl_status_t status + = attribute_store_get_node_attribute_value(node, + REPORTED_ATTRIBUTE, + raw_data.data(), + &value_size); + + if (status != SL_STATUS_OK) { + throw std::runtime_error("Failed to get value for attribute " + + node.name_and_id()); + } + + return raw_data; +} + +void checksum_calculator::add_node(const attribute_store::attribute &node) +{ + if (!node.is_valid()) { + sl_log_error(LOG_TAG, "Can't find node %d. Not adding to checksum.", node); + throw std::runtime_error("Invalid node"); + } + + // Will throw and exception if the conversion failed + auto raw_data = get_raw_data_from_node(node); + + // Add the raw data to the checksum data + auto storage_type = attribute_store_get_storage_type(node.type()); + + // Remove the NULL terminator if we are dealing with a string + if (storage_type == C_STRING_STORAGE_TYPE) { + raw_data.pop_back(); + } + + // Send it as is but append the size of the value at the beginning + if (storage_type == C_STRING_STORAGE_TYPE + || storage_type == BYTE_ARRAY_STORAGE_TYPE + || storage_type == FIXED_SIZE_STRUCT_STORAGE_TYPE + || storage_type == INVALID_STORAGE_TYPE) { + raw_data.insert(raw_data.begin(), raw_data.size()); + checksum_data.insert(checksum_data.end(), raw_data.begin(), raw_data.end()); + } + // Otherwise the MSB is always the first in Z-Wave frames + // (and in attribute store it is last) so we need to reverse the order + else { + checksum_data.insert(checksum_data.end(), + raw_data.rbegin(), + raw_data.rend()); + } +} + +user_credential_checksum_t checksum_calculator::compute_checksum() +{ + user_credential_checksum_t computed_checksum = 0; + // If checksum data is empty, the checksum is 0. The guard is present to avoid + // zwave_controller_crc16 to return CRC_INITIALIZATION_VALUE if checksum_data is empty. + // See CC:0083.01.19.11.016 & CC:0083.01.17.11.013 + if (checksum_data.size() > 0) { + computed_checksum = zwave_controller_crc16(CRC_INITIALIZATION_VALUE, + checksum_data.data(), + checksum_data.size()); + } + return computed_checksum; +} + +} // namespace user_credential \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_checksum_calculator.h b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_checksum_calculator.h new file mode 100644 index 0000000000..9e54c2c4f7 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_checksum_calculator.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +#ifndef USER_CREDENTIAL_CHECKSUM_CALCULATOR_H +#define USER_CREDENTIAL_CHECKSUM_CALCULATOR_H + +// Cpp includes +#include + +// Unify +#include "attribute.hpp" + +// Types +#include "zwave_command_class_user_credential_types.h" + +namespace user_credential +{ + +/** + * @brief Compute the checksum based on the attribute store + * + */ +class checksum_calculator +{ + public: + /** + * @brief Compute a node value and add it to the current checksum + * + * @param node Node to compute the checksum from + * + * @throws std::runtime_error If the node is invalid or if the conversion failed + */ + void add_node(const attribute_store::attribute &attribute); + /** + * @brief Compute the checksum of the added nodes + * + * @note If no nodes are added, the checksum is 0 (see CC:0083.01.19.11.016 & CC:0083.01.17.11.013) + * + * @return user_credential_checksum_t + */ + user_credential_checksum_t compute_checksum(); + + private: + std::vector checksum_data; +}; + +} // namespace user_credential + +#endif // USER_CREDENTIAL_CHECKSUM_CALCULATOR_H \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_capabilities.cpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_capabilities.cpp new file mode 100644 index 0000000000..0d8f5e639b --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_capabilities.cpp @@ -0,0 +1,66 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#include "user_credential_credential_capabilities.h" + +// Get attribute store names +#include "attribute_store_defined_attribute_types.h" + +// Boost +#include + +// Common definitions +#include "user_credential_definitions.hpp" + +namespace user_credential +{ + +credential_capabilities::credential_capabilities( + const attribute_store::attribute &endpoint_node) +{ + this->is_data_valid = false; + + try { + this->credential_checksum_support + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM)) + .reported(); + this->admin_code_support + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE)) + .reported(); + this->admin_code_deactivation_support + = endpoint_node + .child_by_type(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE_DEACTIVATION)) + .reported(); + + this->is_data_valid = true; + } catch (std::exception &e) { + sl_log_error(LOG_TAG, + "Something was wrong getting credential capabilities : %s", + e.what()); + } +} + +bool credential_capabilities::is_credential_checksum_supported() const +{ + return is_data_valid && credential_checksum_support > 0; +} +bool credential_capabilities::is_admin_code_supported() const +{ + return is_data_valid && admin_code_support > 0; +} +bool credential_capabilities::is_admin_code_deactivation_supported() const +{ + return is_data_valid && admin_code_deactivation_support > 0; +} + +} // namespace user_credential diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_capabilities.h b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_capabilities.h new file mode 100644 index 0000000000..eb5fb3dc25 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_capabilities.h @@ -0,0 +1,44 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef USER_CREDENTIAL_CREDENTIAL_CAPABILITIES_H +#define USER_CREDENTIAL_CREDENTIAL_CAPABILITIES_H + +// Attribute store +#include "attribute.hpp" + +namespace user_credential +{ + +class credential_capabilities +{ + public: + explicit credential_capabilities( + const attribute_store::attribute &endpoint_node); + ~credential_capabilities() = default; + + bool is_credential_checksum_supported() const; + bool is_admin_code_supported() const; + bool is_admin_code_deactivation_supported() const; + + private: + uint8_t credential_checksum_support = 0; + uint8_t admin_code_support = 0; + uint8_t admin_code_deactivation_support = 0; + + bool is_data_valid = false; +}; + +} // namespace user_credential + +#endif // USER_CREDENTIAL_CREDENTIAL_CAPABILITIES_H \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_type_capabilities.cpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_type_capabilities.cpp new file mode 100644 index 0000000000..8d434a7ac2 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_type_capabilities.cpp @@ -0,0 +1,208 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#include "user_credential_credential_type_capabilities.h" + +// Get attribute store names +#include "attribute_store_defined_attribute_types.h" + +// UTF16 conversion (deprecated in C++17 but we don't have a better alternative yet) +// Needed for credential data (password) per specification +#include +#include + +// Boost +#include + +// Common definitions +#include "user_credential_definitions.hpp" + +namespace user_credential +{ + +credential_type_capabilities::credential_type_capabilities( + const attribute_store::attribute &endpoint_node, + user_credential_type_t credential_type) +{ + this->is_data_valid = false; + + try { + auto supported_credential_type_node = endpoint_node.child_by_type_and_value( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + credential_type); + + if (!supported_credential_type_node.is_valid()) { + sl_log_error( + LOG_TAG, + "Credential type %d not supported. Can't get capabilities for it.", + credential_type); + return; + } + + this->max_slot_count + = supported_credential_type_node + .child_by_type(ATTRIBUTE(CREDENTIAL_SUPPORTED_SLOT_COUNT)) + .reported(); + this->learn_support = supported_credential_type_node + .child_by_type(ATTRIBUTE(CREDENTIAL_LEARN_SUPPORT)) + .reported(); + this->min_credential_length + = supported_credential_type_node + .child_by_type(ATTRIBUTE(CREDENTIAL_MIN_LENGTH)) + .reported(); + this->max_credential_length + = supported_credential_type_node + .child_by_type(ATTRIBUTE(CREDENTIAL_MAX_LENGTH)) + .reported(); + this->learn_recommended_timeout + = supported_credential_type_node + .child_by_type(ATTRIBUTE(CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT)) + .reported(); + this->learn_number_of_steps + = supported_credential_type_node + .child_by_type(ATTRIBUTE(CREDENTIAL_LEARN_NUMBER_OF_STEPS)) + .reported(); + + this->credential_type = credential_type; + this->is_data_valid = true; + } catch (std::exception &e) { + sl_log_error(LOG_TAG, + "Something was wrong getting credential capabilities : %s", + e.what()); + } +} + +bool credential_type_capabilities::is_learn_supported() const +{ + return is_data_valid && learn_support > 0; +} + +bool credential_type_capabilities::is_credential_valid( + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const std::vector &credential_data) const +{ + if (!is_data_valid) { + sl_log_error( + LOG_TAG, + "Credential capabilities are not valid. Try restarting the device."); + return false; + } + + if (credential_type != this->credential_type) { + sl_log_error(LOG_TAG, "Credential type mismatch."); + return false; + } + + if (!is_slot_valid(credential_slot)) { + sl_log_error( + LOG_TAG, + "Slot ID is not valid. Given : %d, Max Supported Slot count : %d", + credential_slot, + max_slot_count); + return false; + } + + if (!is_credential_data_valid(credential_data)) { + sl_log_error(LOG_TAG, + "Credential data size is not valid. Should be between %d " + "and %d, given : %d", + min_credential_length, + max_credential_length, + credential_data.size()); + return false; + } + + return true; +} + +bool credential_type_capabilities::is_slot_valid( + user_credential_slot_t credential_slot) const +{ + return credential_slot <= max_slot_count; +} + +bool credential_type_capabilities::is_credential_data_valid( + const std::vector &credential_data) const +{ + return (credential_data.size() >= min_credential_length + && credential_data.size() <= max_credential_length); +} + +std::vector + credential_type_capabilities::convert_and_validate_credential_data( + const char *credential_data, user_credential_slot_t credential_slot) const +{ + std::vector credential_data_vector + = convert_credential_data(credential_data); + + // Credential not valid, we are not adding it + if (!this->is_credential_valid(this->credential_type, + credential_slot, + credential_data_vector)) { + throw std::runtime_error("Credential capabilities are not valid."); + } + + return credential_data_vector; +} + +std::vector + credential_type_capabilities::convert_credential_data(const char *credential_data) const +{ + std::vector credential_data_vector; + std::string credential_data_str(credential_data); + switch (credential_type) { + case CREDENTIAL_REPORT_PASSWORD: { + // CC:0083.01.0A.11.021 Passwords MUST be transmitted in Unicode UTF-16 format, in big endian order + auto credential_data_utf16 = utf8_to_utf16(credential_data_str); + for (const auto &c: credential_data_utf16) { + credential_data_vector.push_back((uint8_t)(c >> 8)); + credential_data_vector.push_back((uint8_t)c); + } + } break; + case CREDENTIAL_REPORT_PIN_CODE: + for (const auto &c: credential_data_str) { + if (c < '0' || c > '9') { + throw std::runtime_error( + (boost::format("Invalid character in PIN code : %1%. Only digits " + "are allowed.") + % c) + .str()); + } + credential_data_vector.push_back(c); + } + break; + default: + for (const auto &c: credential_data_str) { + credential_data_vector.push_back(c); + } + } + + return credential_data_vector; +} + +uint8_t credential_type_capabilities::get_learn_recommended_timeout() const +{ + return learn_recommended_timeout; +} + +std::u16string credential_type_capabilities::utf8_to_utf16(const std::string &utf8) const +{ + std::wstring_convert, char16_t> cnv; + std::u16string s = cnv.from_bytes(utf8); + if (cnv.converted() < utf8.size()) + throw std::runtime_error("Something went wrong converting UTF8 to UTF16"); + return s; +} + +} // namespace user_credential \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_type_capabilities.h b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_type_capabilities.h new file mode 100644 index 0000000000..4f71aede74 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_credential_type_capabilities.h @@ -0,0 +1,94 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef USER_CREDENTIAL_CREDENTIAL_TYPE_CAPABILITIES_H +#define USER_CREDENTIAL_CREDENTIAL_TYPE_CAPABILITIES_H + +// Cpp definitions +#include +#include + +// Attribute store +#include "attribute.hpp" +// User credential types +#include "zwave_command_class_user_credential_types.h" + +namespace user_credential +{ + +class credential_type_capabilities +{ + public: + explicit credential_type_capabilities( + const attribute_store::attribute &endpoint_node, + user_credential_type_t credential_type); + ~credential_type_capabilities() = default; + + bool is_learn_supported() const; + + bool is_credential_valid(user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const std::vector &credential_data) const; + + bool is_slot_valid(user_credential_slot_t credential_slot) const; + bool + is_credential_data_valid(const std::vector &credential_data) const; + + /** + * @brief Convert and validate credential data str to a vector of uint8_t + * + * Convenience function to convert data and check if it is valid as per the credential capabilities. + * + * @param credential_data Credential data to convert + * @param credential_slot Credential slot + * + * @throws std::runtime_error if the credential data is invalid + * + * @return The converted data + */ + std::vector convert_and_validate_credential_data( + const char *credential_data, user_credential_slot_t credential_slot) const; + + /** + * @brief Convert credential data str to a vector of uint8_t + * + * @note CC:0083.01.0A.11.021 Passwords MUST be transmitted in Unicode UTF-16 format, in big endian order + * + * @param credential_data Credential data to convert + * + * @throws std::runtime_error if the credential data is invalid + * + * @return The converted data +*/ + std::vector convert_credential_data(const char *credential_data) const; + + uint8_t get_learn_recommended_timeout() const; + + private: + + std::u16string utf8_to_utf16(const std::string &utf8) const; + + user_credential_type_t credential_type = 0; + uint16_t max_slot_count = 0; + uint8_t learn_support = 0; + uint8_t min_credential_length = 0; + uint8_t max_credential_length = 0; + uint8_t learn_recommended_timeout = 0; + uint8_t learn_number_of_steps = 0; + + bool is_data_valid = false; +}; + +} // namespace user_credential + +#endif // USER_CREDENTIAL_CREDENTIAL_TYPE_CAPABILITIES_H \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_definitions.hpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_definitions.hpp new file mode 100644 index 0000000000..a30eccc9f6 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_definitions.hpp @@ -0,0 +1,26 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef USER_CREDENTIAL_DEFINITIONS_HPP +#define USER_CREDENTIAL_DEFINITIONS_HPP + +// Log +#include "sl_log.h" + +#ifndef ATTRIBUTE +#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_##type +#endif + +constexpr char LOG_TAG[] = "zwave_command_class_user_credential"; + +#endif // USER_CREDENTIAL_DEFINITIONS_HPP \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_helpers.cpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_helpers.cpp new file mode 100644 index 0000000000..b110ab7188 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_helpers.cpp @@ -0,0 +1,294 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Get attribute store names +#include "user_credential_helpers.hpp" + +// Boost +#include "boost/format.hpp" + +// Cpp standard includes +#include +namespace user_credential_helpers +{ + + +void set_operation_type(attribute_store::attribute base_node, + attribute_store_type_t operation_type_node_type, + user_credential_operation_type_t operation_type) +{ + auto operation_type_node = base_node.emplace_node(operation_type_node_type); + + // Undefine reported to be sure that we can so the same operation twice in a row + operation_type_node.clear_reported(); + operation_type_node.set_desired(operation_type); +} + +void set_user_operation_type(attribute_store_node_t user_node, + user_credential_operation_type_t operation_type) +{ + set_operation_type( + user_node, + ATTRIBUTE(USER_OPERATION_TYPE), + operation_type); +} + +void set_credential_operation_type( + attribute_store_node_t slot_node, + user_credential_operation_type_t operation_type) +{ + set_operation_type(slot_node, + ATTRIBUTE(CREDENTIAL_OPERATION_TYPE), + operation_type); +} + +void set_credential_learn_operation_type( + attribute_store_node_t slot_node, + user_credential_operation_type_t operation_type) +{ + set_operation_type(slot_node, + ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE), + operation_type); +} + +bool user_exists(attribute_store::attribute endpoint_node, + user_credential_user_unique_id_t user_id) +{ + return endpoint_node + .child_by_type_and_value(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + REPORTED_ATTRIBUTE) + .is_valid(); +} + +attribute_store::attribute + get_user_unique_id_node(attribute_store::attribute endpoint_node, + user_credential_user_unique_id_t user_id, + attribute_store_node_value_state_t state) +{ + attribute_store::attribute user_id_node + = endpoint_node.child_by_type_and_value(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + state); + + if (!user_id_node.is_valid()) { + throw std::runtime_error( + (boost::format("User ID %1% not found (state : %2%).") % user_id % state) + .str()); + } + + return user_id_node; +} + + +attribute_store::attribute + get_credential_type_node(attribute_store::attribute user_id_node, + user_credential_type_t cred_type, + attribute_store_node_value_state_t state) +{ + if (!user_id_node.is_valid()) { + throw std::runtime_error( + "get_credential_type_node: User ID node is not valid."); + } + + attribute_store::attribute cred_type_node + = user_id_node.child_by_type_and_value(ATTRIBUTE(CREDENTIAL_TYPE), + cred_type, + state); + + if (!cred_type_node.is_valid()) { + throw std::runtime_error( + (boost::format("Credential type %1% (state : %2%) not found for %3%.") + % cred_type % state % user_id_node.value_to_string()) + .str()); + } + + return cred_type_node; +} + +attribute_store::attribute + get_credential_slot_node(attribute_store::attribute cred_type_node, + user_credential_slot_t cred_slot, + attribute_store_node_value_state_t state) +{ + if (!cred_type_node.is_valid()) { + throw std::runtime_error( + "get_credential_slot_node: Credential Type node is not valid."); + } + + attribute_store::attribute cred_slot_node + = cred_type_node.child_by_type_and_value(ATTRIBUTE(CREDENTIAL_SLOT), + cred_slot, + state); + + if (!cred_slot_node.is_valid()) { + throw std::runtime_error( + (boost::format( + "Credential slot %1% (state : %2%) not found for %3% / %4%.") + % cred_slot % state % cred_type_node.value_to_string() + % cred_type_node.parent().value_to_string()) + .str()); + } + + return cred_slot_node; +} + +void for_each_credential_type_nodes_for_user( + attribute_store::attribute user_id_node, + const attribute_callback &callback, + user_credential_type_t credential_type) +{ + auto credential_type_nodes + = user_id_node.children(ATTRIBUTE(CREDENTIAL_TYPE)); + for (auto &credential_type_node: credential_type_nodes) { + // Call + if (credential_type == 0 + || (credential_type_node.reported_exists() + && credential_type_node.reported() + == credential_type)) { + callback(credential_type_node); + } + } +} + +void for_each_credential_type_nodes(attribute_store::attribute endpoint_node, + const attribute_callback &callback, + user_credential_type_t credential_type) +{ + auto user_nodes = endpoint_node.children(ATTRIBUTE(USER_UNIQUE_ID)); + for (auto &user_node: user_nodes) { + for_each_credential_type_nodes_for_user(user_node, + callback, + credential_type); + } +} + + +bool is_credential_available(attribute_store_node_t endpoint_node, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot) +{ + bool credential_available = true; + + for_each_credential_type_nodes( + endpoint_node, + [&credential_available, &credential_slot]( + attribute_store::attribute ¤t_credential_type_node) { + for (auto ¤t_credential_slot_node: + current_credential_type_node.children(ATTRIBUTE(CREDENTIAL_SLOT))) { + // If this credential slot node doesn't have a reported value, check the next one + if (!current_credential_slot_node.reported_exists()) { + continue; + } + + if (current_credential_slot_node.reported() + == credential_slot) { + credential_available = false; + return; + } + } + }, + credential_type); + + return credential_available; +} + + +credential_id_nodes + get_credential_identifier_nodes(attribute_store_node_t child_node) +{ + attribute_store::attribute slot_node(child_node); + slot_node = slot_node.first_parent_or_self(ATTRIBUTE(CREDENTIAL_SLOT)); + attribute_store::attribute type_node + = slot_node.first_parent(ATTRIBUTE(CREDENTIAL_TYPE)); + attribute_store::attribute user_unique_id_node + = type_node.first_parent(ATTRIBUTE(USER_UNIQUE_ID)); + + if (!slot_node.is_valid()) { + throw std::runtime_error( + "get_credential_identifier_nodes: Can't get credential slot node."); + } + + if (!type_node.is_valid()) { + throw std::runtime_error( + "get_credential_identifier_nodes: Can't get credential type node."); + } + + if (!user_unique_id_node.is_valid()) { + throw std::runtime_error( + "get_credential_identifier_nodes: Can't get user unique ID node."); + } + + return {.slot_node = slot_node, + .type_node = type_node, + .user_unique_id_node = user_unique_id_node}; +} + +credential_id_nodes get_credential_identifier_nodes( + const attribute_store::attribute &endpoint_node, + identifier_state user_id, + identifier_state credential_type, + identifier_state credential_slot) +{ + credential_id_nodes nodes; + + nodes.user_unique_id_node + = get_user_unique_id_node(endpoint_node, user_id.value, user_id.state); + + if (!nodes.user_unique_id_node.is_valid()) { + throw std::runtime_error( + "get_credential_identifier_nodes: Can't get user unique ID " + + std::to_string(user_id.value)); + } + + nodes.type_node = get_credential_type_node(nodes.user_unique_id_node, + credential_type.value, + credential_type.state); + + if (!nodes.type_node.is_valid()) { + throw std::runtime_error( + (boost::format("get_credential_identifier_nodes: Can't get credential " + "type %1% for user %2%") + % credential_type.value % user_id.value) + .str()); + } + + nodes.slot_node = get_credential_slot_node(nodes.type_node, + credential_slot.value, + credential_slot.state); + + if (!nodes.slot_node.is_valid()) { + throw std::runtime_error( + (boost::format("get_credential_identifier_nodes: Can't get credential " + "slot %1% for credential type %2% / user %3%") + % credential_slot.value % credential_type.value % user_id.value) + .str()); + } + return nodes; +} + +bool is_admin_code_empty(const std::vector& admin_pin_code) +{ + return admin_pin_code.size() == 1 && admin_pin_code[0] == 0; +} + +void set_empty_admin_code(attribute_store::attribute &admin_pin_code_node, + attribute_store_node_value_state_t state) +{ + if (!admin_pin_code_node.is_valid()) { + throw std::runtime_error("Admin code node is not valid."); + } + std::vector empty_code = {0}; + admin_pin_code_node.set(state, empty_code); +} + +} // namespace user_credential_helpers \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_helpers.hpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_helpers.hpp new file mode 100644 index 0000000000..cf67f66bcf --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_helpers.hpp @@ -0,0 +1,281 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef USER_CREDENTIAL_HELPERS_H +#define USER_CREDENTIAL_HELPERS_H + +// Get attribute store names +#include "attribute_store_defined_attribute_types.h" +// User credential types +#include "zwave_command_class_user_credential_types.h" + +// Unify Cpp +#include "attribute.hpp" +#include "user_credential_definitions.hpp" + +namespace user_credential_helpers +{ + +using attribute_callback = std::function; + +///////////////////////////////////////////////////////////////////////////// +// Data struct +///////////////////////////////////////////////////////////////////////////// + +// Represent a credential ID (slot, type, user unique ID) +struct credential_id_nodes { + attribute_store::attribute slot_node; + attribute_store::attribute type_node; + attribute_store::attribute user_unique_id_node; +}; + +/** + * @brief Update desired value if found, or create the node otherwise + * + * Check for the value in the desired value of attribute_type (with parent base_node). + * If we found it, we update the reported value and clear the desired value. + * Otherwise we create the node with the given value and set it to reported. + * + * @tparam T Type of the value to set + * + * @param base_node Base node to search for the attribute + * @param attribute_type Type of the attribute to search for + * @param value Value to search/set + * + * @return attribute_store::attribute Node that was created/updated + */ +template attribute_store::attribute + create_or_update_desired_value(attribute_store::attribute base_node, + attribute_store_type_t attribute_type, + T value) +{ + auto node = base_node.child_by_type_and_value(attribute_type, + value, + DESIRED_ATTRIBUTE); + if (!node.is_valid()) { + node = base_node.emplace_node(attribute_type, value); + } else { + node.set_reported(value); + node.clear_desired(); + } + + return node; +} + +/** + * @brief Create operation_type_node_type if it doesn't exists, and set the desired value to operation_type (and clear reported) + * + * @see set_user_operation_type + * @see set_credential_operation_type + * @see set_credential_learn_operation_type + * + * @param base_node Base node to search for the attribute + * @param operation_type_node_type Type of the operation type node + * @param operation_type Operation type to set + * + */ +void set_operation_type(attribute_store::attribute base_node, + attribute_store_type_t operation_type_node_type, + user_credential_operation_type_t operation_type); +/** + * @brief Set User Operation + * + * Set the operation type as desired and clear reported to call SET function + * + * @param user_node User node + * @param operation_type Operation type to set + * + */ +void set_user_operation_type(attribute_store_node_t user_node, + user_credential_operation_type_t operation_type); + +/** + * @brief Set Credential Operation + * + * Set the operation type as desired and clear reported to call SET function + * + * @param slot_node Slot node + * @param operation_type Operation type to set + * + */ +void set_credential_operation_type( + attribute_store_node_t slot_node, + user_credential_operation_type_t operation_type); + +/** + * @brief Set Credential Learn Operation + * + * Set the operation type as desired and clear reported to call SET function + * + * @param slot_node Slot node + * @param operation_type Operation type to set + */ +void set_credential_learn_operation_type( + attribute_store_node_t slot_node, + user_credential_operation_type_t operation_type); + +/** + * @brief Get node associated with user ID (desired or reported) + * + * @param endpoint_node Current endpoint node + * @param user_id User ID + * + * @return True is user exists, false otherwise + */ +bool user_exists(attribute_store::attribute endpoint_node, + user_credential_user_unique_id_t user_id); + +/** + * @brief Get node associated with user ID (desired or reported) + * + * @param endpoint_node Current endpoint node + * @param user_id User ID + * @param state Check reported or desired value (or desired else reported) + * + * @throws std::runtime_error If User ID does not exist with given state + * + * @return User ID Node + */ +attribute_store::attribute + get_user_unique_id_node(attribute_store::attribute endpoint_node, + user_credential_user_unique_id_t user_id, + attribute_store_node_value_state_t state); + +/** + * @brief Get credential type node associated with user ID + * + * @param user_id_node User ID node + * @param cred_type Credential type + * @param state Check reported or desired value (or desired else reported) + * + * @throws std::runtime_error If Credential type for given user_id_node does not exist with given state + * + * @return Credential type node + */ +attribute_store::attribute + get_credential_type_node(attribute_store::attribute user_id_node, + user_credential_type_t cred_type, + attribute_store_node_value_state_t state); + +/** + * @brief Get credential slot node associated with credential type + * + * @param cred_type_node Credential type node + * @param cred_slot Credential slot + * @param state Check reported or desired value (or desired else reported) + * + * @throws std::runtime_error If Credential slot for given cred_type_node does not exist with given state + * + * @return Credential slot node + */ +attribute_store::attribute + get_credential_slot_node(attribute_store::attribute cred_type_node, + user_credential_slot_t cred_slot, + attribute_store_node_value_state_t state); +/** + * @brief Iterate on each credential type nodes for a given user + * + * @param user_id_node User ID node + * @param callback Callback function to call for each credential type node + * @param credential_type Credential type to find. If 0, process all credential types + */ +void for_each_credential_type_nodes_for_user( + attribute_store::attribute user_id_node, + const attribute_callback &callback, + user_credential_type_t credential_type = 0); + +/** + * @brief Iterate on each credential type nodes + * + * @param endpoint_node Endpoint point node + * @param callback Callback function to call for each credential type node + * @param credential_type Credential type to find. If 0, process all credential types + */ +void for_each_credential_type_nodes(attribute_store::attribute endpoint_node, + const attribute_callback &callback, + user_credential_type_t credential_type = 0); +/** + * @brief Checks if given credential ID (credential type, credential slot) is available + * + * @param endpoint_node Endpoint node + * @param credential_type Credential type + * @param credential_slot Credential slot + * + * @return true Credential is available + * @return false Credential is not available : if an user already have the combination of given credential type and slot. +*/ +bool is_credential_available(attribute_store_node_t endpoint_node, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot); + +/** + * @brief Get associated credential identifier nodes + * + * @param child_node Not that have a CREDENTIAL_SLOT, CREDENTIAL_TYPE and USER_UNIQUE_ID as respective parents + * + * @throws std::runtime_error If one of the nodes is not found + * + * @return credential_id_nodes Credential identifier nodes + */ +credential_id_nodes + get_credential_identifier_nodes(attribute_store_node_t child_node); + +template struct identifier_state { + T value; + attribute_store_node_value_state_t state; +}; +/** + * @brief Get associated credential identifier nodes + * + * @param endpoint_node Endpoint node + * @param user_id User ID with given state + * @param credential_type Credential type with given state + * @param credential_slot Credential slot with given state + * + * @throws std::runtime_error If one of the nodes is not found + * + * @return credential_id_nodes Credential identifier nodes + */ +credential_id_nodes get_credential_identifier_nodes( + const attribute_store::attribute &endpoint_node, + identifier_state user_id, + identifier_state credential_type, + identifier_state credential_slot); + +/** + * @brief Return true if given admin pin code is considered empty + * + * We need this function since the attribute store doesn't support empty vector. + * + * @param admin_pin_code Admin pin code + * + * @return true Admin pin code is empty + * @return false Admin pin code is not empty + */ +bool is_admin_code_empty(const std::vector& admin_pin_code); +/** + * @brief Set the admin pin code node to an empty value + * + * We need this function since the attribute store doesn't support empty vector. + * + * @param admin_pin_code_node Admin pin code node + * @param state State (REPORTED or DESIRED) + * + * @throws std::runtime_error If admin_pin_code_node is not valid + */ +void set_empty_admin_code(attribute_store::attribute &admin_pin_code_node, + attribute_store_node_value_state_t state); + +} // namespace user_credential_helpers + +#endif // USER_CREDENTIAL_HELPERS_H \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_user_capabilities.cpp b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_user_capabilities.cpp new file mode 100644 index 0000000000..833327cae4 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_user_capabilities.cpp @@ -0,0 +1,135 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#include "user_credential_user_capabilities.h" + +// Get attribute store names +#include "attribute_store_defined_attribute_types.h" + +// Common definitions +#include "user_credential_definitions.hpp" + + +namespace user_credential +{ + + +user_capabilities::user_capabilities(attribute_store::attribute endpoint_node) { + try { + this->max_user_count + = endpoint_node.child_by_type(ATTRIBUTE(NUMBER_OF_USERS)) + .reported(); + this->supported_credential_rules_bitmask + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORTED_CREDENTIAL_RULES)) + .reported(); + this->supported_user_types_bitmask + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORTED_USER_TYPES)) + .reported(); + this->max_user_name_length + = endpoint_node.child_by_type(ATTRIBUTE(MAX_USERNAME_LENGTH)) + .reported(); + this->support_user_schedule + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORT_USER_SCHEDULE)) + .reported(); + this->support_all_users_checksum + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORT_ALL_USERS_CHECKSUM)) + .reported(); + this->support_by_user_checksum + = endpoint_node.child_by_type(ATTRIBUTE(SUPPORT_USER_CHECKSUM)) + .reported(); + + + this->is_data_valid = true; + } catch (std::exception &e) { + sl_log_error(LOG_TAG, + "Something was wrong getting user capabilities : %s", + e.what()); + attribute_store_log(); + this->is_data_valid = false; + } +} + + +bool user_capabilities::is_user_valid(user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + const char *user_name) const +{ + if (!is_data_valid) { + sl_log_error(LOG_TAG, + "User capabilities are not valid. Try restarting the device."); + return false; + } + + if (!is_user_id_valid(user_id)) { + sl_log_error(LOG_TAG, "User ID is not valid."); + return false; + } + + if (!is_user_type_supported(user_type)) { + sl_log_error(LOG_TAG, "User type is not supported."); + return false; + } + + if (!is_credential_rule_supported(credential_rule)) { + sl_log_error(LOG_TAG, "Credential rule is not supported."); + return false; + } + + if (!is_user_name_valid(user_name)) { + sl_log_error(LOG_TAG, "User name is not valid."); + return false; + } + return true; +} + +bool user_capabilities::is_user_name_valid(const char *user_name) const +{ + std::string str_user_name(user_name); + return str_user_name.length() <= max_user_name_length; +} + +bool user_capabilities::is_user_id_valid( + user_credential_user_unique_id_t user_id) const +{ + return user_id <= max_user_count; +} + +bool user_capabilities::is_user_type_supported( + user_credential_type_t user_type) const +{ + return (supported_user_types_bitmask & (1 << user_type)); +} + +bool user_capabilities::is_credential_rule_supported( + user_credential_rule_t credential_rule) const +{ + return (supported_credential_rules_bitmask & (1 << credential_rule)); +} + +bool user_capabilities::is_all_users_checksum_supported() const +{ + return is_data_valid && support_all_users_checksum > 0; +} + +bool user_capabilities::is_user_checksum_supported() const +{ + return is_data_valid && support_by_user_checksum > 0; +} + +bool user_capabilities::is_user_schedule_supported() const +{ + return is_data_valid && support_user_schedule > 0; +} + +} // namespace user_credential \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_user_capabilities.h b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_user_capabilities.h new file mode 100644 index 0000000000..e450e269e7 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/private/user_credential/user_credential_user_capabilities.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef USER_CREDENTIAL_USER_CAPABILITIES_H +#define USER_CREDENTIAL_USER_CAPABILITIES_H + +// Attribute store +#include "attribute.hpp" +// User credential types +#include "zwave_command_class_user_credential_types.h" + + +namespace user_credential +{ + +class user_capabilities +{ + public: + explicit user_capabilities(attribute_store::attribute endpoint_node); + ~user_capabilities() = default; + + /** + * @brief Check if the user proprieties are valid + * + * @note Will return false if is_data_valid is false + * + * @param user_id User ID + * @param user_type User type + * @param credential_rule Credential rule + * @param user_name User name + * + * @return true User is valid + * @return false User is not valid + */ + bool is_user_valid(user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + const char *user_name) const; + + /** + * @brief Checks if the given user name is valid. + * @param user_name The user name to be validated. + * @return true User name is valid + * @return false User name is not valid + */ + bool is_user_name_valid(const char *user_name) const; + + /** + * @brief Check if a user id is valid + * @param user_id User ID to check + * @return true User ID is valid + * @return false User ID is not valid + */ + bool is_user_id_valid(user_credential_user_unique_id_t user_id) const; + /** + * @brief Check if a user type is supported + * @param user_type User type to check + * @return true User type is supported + * @return false User type is not supported + */ + bool is_user_type_supported(user_credential_type_t user_type) const; + + /** + * @brief Check if a credential rule is supported + * @param credential_rule Credential rule to check + * @return true Credential rule is supported + * @return false Credential rule is not supported + */ + bool + is_credential_rule_supported(user_credential_rule_t credential_rule) const; + + /** + * @brief Check if all users checksum is supported + * @return true All users checksum is supported + * @return false All users checksum is not supported + */ + bool is_all_users_checksum_supported() const; + + /** + * @brief Check if user checksum is supported + * @return true User checksum is supported + * @return false User checksum is not supported + */ + bool is_user_checksum_supported() const; + /** + * @brief Check if user schedule is supported + * @return true User schedule is supported + * @return false User schedule is not supported + */ + bool is_user_schedule_supported() const; + + private: + // Maximum number of users that can be stored in the device + uint16_t max_user_count = 0; + // Credential rules supported + uint8_t supported_credential_rules_bitmask = 0; + // User types supported + uint32_t supported_user_types_bitmask = 0; + // Max length for the user names + uint8_t max_user_name_length = 0; + // Device support for scheduling users + uint8_t support_user_schedule = 0; + // Device support for getting the checksum of all users + uint8_t support_all_users_checksum = 0; + // Device support for getting the checksum of a specific user + uint8_t support_by_user_checksum = 0; + + // True if the data is valid inside this struct + bool is_data_valid = false; +}; + +} // namespace user_credential + +#endif // USER_CREDENTIAL_USER_CAPABILITIES_H \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.cpp b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.cpp new file mode 100644 index 0000000000..b44bf54662 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.cpp @@ -0,0 +1,2509 @@ + +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +// System +#include + +#include "zwave_command_class_user_credential.h" +#include "zwave_command_classes_utils.h" +#include "ZW_classcmd.h" + +// Includes from other ZPC Components +#include "zwave_command_class_indices.h" +#include "zwave_command_handler.h" +#include "zwave_command_class_version_types.h" +#include "attribute_store_defined_attribute_types.h" +#include "zpc_attribute_store.h" +#include "zwave_controller_crc16.h" + +// Unify +#include "attribute_resolver.h" +#include "attribute_store.h" +#include "attribute_store_helper.h" +#include "attribute_store_type_registration.h" + +// DotDot +#include "unify_dotdot_attribute_store_node_state.h" +#include "dotdot_mqtt_helpers.hpp" + +// Cpp related +#include +#include +#include +#include +#include + +// Cpp Attribute store +#include "attribute.hpp" +#include "zwave_frame_generator.hpp" +#include "zwave_frame_parser.hpp" + +// Private helpers +#include "private/user_credential/user_credential_definitions.hpp" +#include "private/user_credential/user_credential_user_capabilities.h" +#include "private/user_credential/user_credential_credential_capabilities.h" +#include "private/user_credential/user_credential_credential_type_capabilities.h" +#include "private/user_credential/user_credential_checksum_calculator.h" +#include "private/user_credential/user_credential_helpers.hpp" + +// Using +using namespace user_credential_helpers; + +/** + * @brief Implementation notes + * + * 1. Perform mandatory interview with User and Credentials Capabilities + * 2. Once interview is finished we retrieve all Users/Credentials (see zwave_network_status_changed) + * > To get all Users and Credential we create a new node with a desired value. + * > The lack of reported value will trigger a GET + * > GET will set the reported value so we can get a report for this USER/CREDENTIAL + * + */ + +namespace +{ +zwave_frame_generator frame_generator( + COMMAND_CLASS_USER_CREDENTIAL); //NOSONAR - false positive since it is warped in a namespace + +// Callbacks +std::set + user_credential_slot_changed_callback; //NOSONAR - false positive since it is warped in a namespace +std::set + user_credential_slot_message_callback; //NOSONAR - false positive since it is warped in a namespace +} // namespace + +/** + * @brief Keep track of the interview state + * + * User interview start with a get on User 0 to get the first user. + * We keep this node to store all the credentials that are not assigned to a user. + * + * So we need to set its reported in the first User Report otherwise the first GET will + * never be marked as resolved. + * + * We also need to keep track of the next user to interview, so we can first get all the + * credential for the current user before moving to the next one. + */ +namespace users_interview_state +{ +// WARNING : Use functions instead of those variables +// Next user ID to be interviewed +user_credential_user_unique_id_t next_user_id = 0; +// Special node for user 0 +// Used to resolve it in the report instead of in the get to prevent resolver issues +attribute_store::attribute user_0_node = ATTRIBUTE_STORE_INVALID_NODE; + +/** + * @brief Mark an node as the user 0 node + * + * @param node Node to mark as user 0 + */ +void set_user_0_node(attribute_store::attribute node) +{ + sl_log_debug(LOG_TAG, "Starting interview for all users on the device."); + user_0_node = node; +} + +/** + * @brief Resolve user 0 if needed + */ +void resolve_user_0_node() +{ + if (user_0_node == ATTRIBUTE_STORE_INVALID_NODE) { + return; + } + + try { + user_0_node.set_reported(0); + user_0_node = ATTRIBUTE_STORE_INVALID_NODE; + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, "Error while setting user 0 node : %s", e.what()); + } +} + +/** + * @brief Schedule the next user interview + * + * @param user_id User ID to interview next + */ +void schedule_next_user_interview(user_credential_user_unique_id_t user_id) +{ + sl_log_debug(LOG_TAG, "Schedule a get for next User ID :%d", next_user_id); + next_user_id = user_id; +} + +/** + * @brief Trigger a get for the next user + * + * If there is not next user, we will trigger the all users checksum get + * (if supported) + * + * @param endpoint_node Current endpoint node + */ +void trigger_get_for_next_user(attribute_store::attribute endpoint_node) +{ + // If we get here it means that we have finished the interview for users and + // their credentials + if (next_user_id == 0) { + sl_log_debug(LOG_TAG, "User interview finished"); + // Check if we supports all users checksum to compute it + user_credential::user_capabilities capabilities(endpoint_node); + if (capabilities.is_all_users_checksum_supported()) { + // This will do nothing if the node already exists + // Otherwise it will trigger all_users_checksum_get + endpoint_node.emplace_node(ATTRIBUTE(ALL_USERS_CHECKSUM)); + } + return; + } + + sl_log_debug(LOG_TAG, "Trigger a get for next User ID :%d", next_user_id); + + endpoint_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + next_user_id, + DESIRED_ATTRIBUTE); + + // Reset state + next_user_id = 0; +} +} // namespace users_interview_state + +///////////////////////////////////////////////////////////////////////////// +// Callbacks +///////////////////////////////////////////////////////////////////////////// +void zwave_command_class_user_credential_set_uuic_slot_changed_callback( + user_credential_slot_changed_callback_t callback) +{ + if (callback != nullptr) { + user_credential_slot_changed_callback.insert(callback); + } +} + +void zwave_command_class_user_credential_set_message_callback( + user_credential_slot_message_callback_t callback) +{ + if (callback != nullptr) { + user_credential_slot_message_callback.insert(callback); + } +} + +void send_message_to_mqtt(sl_log_level level, const std::string &message) +{ + if (level == SL_LOG_DEBUG) { + sl_log_critical(LOG_TAG, "Debug message should not be sent to MQTT"); + return; + } + sl_log(LOG_TAG, level, "%s", message.c_str()); + + for (auto &callback: user_credential_slot_message_callback) { + callback(level, message); + } +} + +///////////////////////////////////////////////////////////////////////////// +// Helpers +///////////////////////////////////////////////////////////////////////////// +std::string + get_credential_type_debug_str(user_credential_type_t credential_type) +{ + auto fmt = boost::format("Credential Type %1% (%2%)") + % cred_type_get_enum_value_name(credential_type) + % static_cast(credential_type); + + return fmt.str(); +} + +///////////////////////////////////////////////////////////////////////////// +// Version & Attribute Creation +///////////////////////////////////////////////////////////////////////////// +static void zwave_command_class_user_credential_on_version_attribute_update( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + if (change == ATTRIBUTE_DELETED) { + return; + } + + zwave_cc_version_t version = 0; + attribute_store_get_reported(updated_node, &version, sizeof(version)); + + if (version == 0) { + return; + } + + sl_log_debug(LOG_TAG, "User Credential version %d", version); + + attribute_store::attribute endpoint_node + = attribute_store_get_first_parent_with_type(updated_node, + ATTRIBUTE_ENDPOINT_ID); + + // The order of the attribute matter since it defines the order of the + // Z-Wave get command order. + endpoint_node.emplace_node(ATTRIBUTE(NUMBER_OF_USERS)); + endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM)); +} + +///////////////////////////////////////////////////////////////////////////// +// User Credential User Capabilities Get/Report +///////////////////////////////////////////////////////////////////////////// +static sl_status_t zwave_command_class_user_credential_user_capabilities_get( + [[maybe_unused]] attribute_store_node_t node, + uint8_t *frame, + uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "User Capabilities Get"); + + return frame_generator.generate_no_args_frame(USER_CAPABILITIES_GET, + frame, + frame_length); +} + +sl_status_t zwave_command_class_user_credential_user_capabilities_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + attribute_store::attribute endpoint_node( + zwave_command_class_get_endpoint_node(connection_info)); + + sl_log_debug(LOG_TAG, "User Capabilities Report"); + const uint8_t expected_size = 9; + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(expected_size, expected_size + 4)) { + sl_log_error(LOG_TAG, + "Invalid frame size for User Capabilities Report frame"); + return SL_STATUS_FAIL; + } + + parser.read_sequential( + 2, + endpoint_node.emplace_node(ATTRIBUTE(NUMBER_OF_USERS))); + parser.read_byte( + endpoint_node.emplace_node(ATTRIBUTE(SUPPORTED_CREDENTIAL_RULES))); + parser.read_byte( + endpoint_node.emplace_node(ATTRIBUTE(MAX_USERNAME_LENGTH))); + + parser.read_byte_with_bitmask( + {{USER_CAPABILITIES_REPORT_PROPERTIES1_USER_SCHEDULE_SUPPORT_BIT_MASK, + endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_USER_SCHEDULE))}, + {USER_CAPABILITIES_REPORT_PROPERTIES1_ALL_USERS_CHECKSUM_SUPPORT_BIT_MASK, + endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_ALL_USERS_CHECKSUM))}, + {USER_CAPABILITIES_REPORT_PROPERTIES1_USER_CHECKSUM_SUPPORT_BIT_MASK, + endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_USER_CHECKSUM))}}); + + parser.read_bitmask( + endpoint_node.emplace_node(ATTRIBUTE(SUPPORTED_USER_TYPES))); + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing User Capabilities Report frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// User Credential Credential Capabilities Get/Report +///////////////////////////////////////////////////////////////////////////// +static sl_status_t + zwave_command_class_user_credential_credential_capabilities_get( + [[maybe_unused]] attribute_store_node_t node, + uint8_t *frame, + uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Capabilities Get"); + + return frame_generator.generate_no_args_frame(CREDENTIAL_CAPABILITIES_GET, + frame, + frame_length); +} + +sl_status_t + zwave_command_class_user_credential_credential_capabilities_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Capabilities Report"); + + attribute_store::attribute endpoint_node( + zwave_command_class_get_endpoint_node(connection_info)); + + const uint8_t min_expected_size = 5; + + try { + zwave_frame_parser parser(frame_data, frame_length); + + // We only needs to check the minimum size here + if (!parser.is_frame_size_valid(min_expected_size, UINT8_MAX)) { + sl_log_error( + LOG_TAG, + "Invalid frame size for Credential Capabilities Report frame"); + return SL_STATUS_FAIL; + } + + const uint8_t support_admin_code_bitmask = 0x40; + auto result = parser.read_byte_with_bitmask( + {{CREDENTIAL_CAPABILITIES_REPORT_PROPERTIES1_CREDENTIAL_CHECKSUM_SUPPORT_BIT_MASK, + endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM))}, + {support_admin_code_bitmask, + endpoint_node.emplace_node(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE))}, + {0x20, + endpoint_node.emplace_node( + ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE_DEACTIVATION))}}); + + if (result[support_admin_code_bitmask]) { + endpoint_node.emplace_node(ATTRIBUTE(ADMIN_PIN_CODE)); + } + + uint8_t supported_credential_types_count = parser.read_byte(); + + // Remove all previous known SUPPORTED_CREDENTIAL_TYPE + attribute_store::attribute type_node; + do { + // Take first supported credential type node + endpoint_node.child_by_type(ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE)) + .delete_node(); + } while (endpoint_node.child_by_type(ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE)) + .is_valid()); + + // Compute this value here since we need it for the exposure of the supported user credential types + uint16_t ucl_credential_type_mask = 0; + + // Create each node with credential type + std::vector credential_type_nodes; + for (uint8_t current_credential_type_index = 0; + current_credential_type_index < supported_credential_types_count; + current_credential_type_index++) { + // Create new node + auto current_credential_type_node + = endpoint_node.add_node(ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE)); + // Read credential type and save into the node + auto credential_type = parser.read_byte(current_credential_type_node); + // Compute bitmask for MQTT + ucl_credential_type_mask |= (1 << (credential_type - 1)); + // Save the credential type node for later + credential_type_nodes.push_back(current_credential_type_node); + } + + // CL Support + for (uint8_t current_credential_type_index = 0; + current_credential_type_index < supported_credential_types_count; + current_credential_type_index++) { + // Create new node + auto credential_learn_support_node + = credential_type_nodes[current_credential_type_index].add_node( + ATTRIBUTE(CREDENTIAL_LEARN_SUPPORT)); + parser.read_byte_with_bitmask( + {CREDENTIAL_CAPABILITIES_REPORT_PROPERTIES1_CREDENTIAL_CHECKSUM_SUPPORT_BIT_MASK, + credential_learn_support_node}); + } + + // Number of Supported Credential Slots + for (uint8_t current_credential_type_index = 0; + current_credential_type_index < supported_credential_types_count; + current_credential_type_index++) { + auto credential_learn_support_node + = credential_type_nodes[current_credential_type_index].add_node( + ATTRIBUTE(CREDENTIAL_SUPPORTED_SLOT_COUNT)); + + parser.read_sequential(2, credential_learn_support_node); + } + + auto create_and_store_uint8_value = [&](attribute_store_type_t type) { + for (uint8_t current_credential_type_index = 0; + current_credential_type_index < supported_credential_types_count; + current_credential_type_index++) { + auto node + = credential_type_nodes[current_credential_type_index].add_node(type); + parser.read_byte(node); + } + }; + + create_and_store_uint8_value(ATTRIBUTE(CREDENTIAL_MIN_LENGTH)); + create_and_store_uint8_value(ATTRIBUTE(CREDENTIAL_MAX_LENGTH)); + create_and_store_uint8_value( + ATTRIBUTE(CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT)); + create_and_store_uint8_value(ATTRIBUTE(CREDENTIAL_LEARN_NUMBER_OF_STEPS)); + + // Set UCL mask for supported user credential types + endpoint_node + .emplace_node( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES) + .set_reported(ucl_credential_type_mask); + } catch (const std::exception &e) { + sl_log_error( + LOG_TAG, + "Error while parsing Credential Capabilities Report frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// All User Checksum Get/Report +///////////////////////////////////////////////////////////////////////////// + +/** + * @brief Add given user node to the checksum calculator + * + * @param user_node User node + * @param checksum_calculator Checksum calculator + * @param include_user_identifier Include the user identifier in the checksum (used in ALL_USERS_CHECKSUM) + */ +void add_user_node_to_checksum( + const attribute_store::attribute &user_node, + user_credential::checksum_calculator &checksum_calculator, + bool include_user_identifier = false) +{ + // Check if we need to add the identifier to the checksum calculation + if (include_user_identifier) { + checksum_calculator.add_node(user_node); + } + + // Gather all the User values + const std::vector user_attributes = { + ATTRIBUTE(USER_TYPE), + ATTRIBUTE(USER_ACTIVE_STATE), + ATTRIBUTE(CREDENTIAL_RULE), + ATTRIBUTE(USER_NAME_ENCODING), + ATTRIBUTE(USER_NAME), + }; + + for (auto attribute: user_attributes) { + checksum_calculator.add_node(user_node.child_by_type(attribute)); + } + + // The all credential data + for (auto credential_type_node: + user_node.children(ATTRIBUTE(CREDENTIAL_TYPE))) { + for (auto credential_slot_node: + credential_type_node.children(ATTRIBUTE(CREDENTIAL_SLOT))) { + if (!credential_slot_node.reported_exists()) { + sl_log_debug( + LOG_TAG, + "%d reported value is not defined. Not adding to checksum.", + credential_slot_node.value_to_string()); + continue; + } + + // Add credential type to checksum + checksum_calculator.add_node(credential_type_node); + // Add credential slot to checksum + checksum_calculator.add_node(credential_slot_node); + checksum_calculator.add_node( + credential_slot_node.child_by_type(ATTRIBUTE(CREDENTIAL_DATA))); + } + } +} + +static sl_status_t zwave_command_class_user_credential_all_user_checksum_get( + [[maybe_unused]] attribute_store_node_t node, + uint8_t *frame, + uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "All Users Checksum Get"); + + return frame_generator.generate_no_args_frame(ALL_USERS_CHECKSUM_GET, + frame, + frame_length); +} + +sl_status_t zwave_command_class_user_credential_all_user_checksum_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_log_debug(LOG_TAG, "All Users Checksum Report"); + constexpr uint8_t expected_size = sizeof(ZW_ALL_USERS_CHECKSUM_REPORT_FRAME); + + attribute_store::attribute endpoint_node + = zwave_command_class_get_endpoint_node(connection_info); + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(expected_size)) { + sl_log_error(LOG_TAG, + "Invalid frame size for All User Checksum Report frame"); + return SL_STATUS_NOT_SUPPORTED; + } + + auto received_checksum = parser.read_sequential( + 2, + endpoint_node.emplace_node(ATTRIBUTE(ALL_USERS_CHECKSUM))); + + // Create the checksum calculator + user_credential::checksum_calculator checksum_calculator; + + // Add all user nodes to the checksum + for (auto user_node: endpoint_node.children(ATTRIBUTE(USER_UNIQUE_ID))) { + // Ignore user node 0 + if (user_node.reported_exists() + && user_node.reported() == 0) { + continue; + } + add_user_node_to_checksum(user_node, checksum_calculator, true); + } + + // Compute the checksum + auto computed_checksum = checksum_calculator.compute_checksum(); + if (computed_checksum != received_checksum) { + auto message + = boost::format( + "All Users Checksum mismatch. Received %1$#x but computed %2$#x") + % received_checksum % computed_checksum; + send_message_to_mqtt(SL_LOG_ERROR, message.str()); + return SL_STATUS_FAIL; + } else { + send_message_to_mqtt(SL_LOG_INFO, "All Users Checksum match."); + } + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing All User Checksum Report frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// Credential Set/Get/Report +///////////////////////////////////////////////////////////////////////////// + +/** + * @brief Trigger a GET credential command + * + * Create credential_type (reported) and credential_slot (desired) nodes if they don't exist + * + * trigger_get_credential(user_node, 0, 0) will trigger a GET command for the first credential of user_node + * + * @param user_unique_id_node User ID node + * @param credential_type 0 to get the first credential; valid value otherwise + * @param credential_slot 0 to get the first credential; valid value otherwise + * +*/ +void trigger_get_credential(attribute_store::attribute &user_unique_id_node, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot) +{ + sl_log_debug(LOG_TAG, + "Trigger GET credential for user %d : " + "Credential type %s, credential slot %d", + user_unique_id_node.reported(), + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + user_unique_id_node + .emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type, + REPORTED_ATTRIBUTE) + .emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + DESIRED_ATTRIBUTE); +} + +sl_status_t zwave_command_class_user_credential_credential_set( + attribute_store_node_t credential_operation_type_node, + uint8_t *frame, + uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Set"); + try { + auto cred_nodes + = get_credential_identifier_nodes(credential_operation_type_node); + + auto operation_type + = cred_nodes.slot_node.child_by_type(ATTRIBUTE(CREDENTIAL_OPERATION_TYPE)) + .desired(); + + sl_log_debug(LOG_TAG, "Operation type : %d", operation_type); + + // Generate the frame + const bool is_delete_operation + = (operation_type == CREDENTIAL_SET_OPERATION_TYPE_DELETE); + + uint8_t expected_frame_size = 9; + uint8_t credential_size = 0; + auto credential_data_node + = cred_nodes.slot_node.child_by_type(ATTRIBUTE(CREDENTIAL_DATA)); + + if (!is_delete_operation) { + auto state = REPORTED_ATTRIBUTE; + if (credential_data_node.desired_exists()) { + state = DESIRED_ATTRIBUTE; + } + credential_size = static_cast( + credential_data_node.get>(state).size()); + } + + // Append the credential data + expected_frame_size += credential_size; + + frame_generator.initialize_frame(CREDENTIAL_SET, + frame, + expected_frame_size); + frame_generator.add_value(cred_nodes.user_unique_id_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(cred_nodes.type_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(cred_nodes.slot_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_raw_byte(operation_type); + frame_generator.add_raw_byte(credential_size); + if (!is_delete_operation) { + frame_generator.add_value(credential_data_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + } + + frame_generator.validate_frame(frame_length); + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating Credential Set frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +static sl_status_t zwave_command_class_user_credential_credential_get( + attribute_store_node_t credential_slot_node, + uint8_t *frame, + uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Get"); + + // Generate the frame + constexpr auto expected_frame_size + = static_cast(sizeof(ZW_CREDENTIAL_GET_FRAME)); + try { + auto cred_nodes = get_credential_identifier_nodes(credential_slot_node); + + frame_generator.initialize_frame(CREDENTIAL_GET, + frame, + expected_frame_size); + frame_generator.add_value(cred_nodes.user_unique_id_node, + REPORTED_ATTRIBUTE); + frame_generator.add_value(cred_nodes.type_node, REPORTED_ATTRIBUTE); + frame_generator.add_value(cred_nodes.slot_node, DESIRED_ATTRIBUTE); + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating Credential Get frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +enum class credential_report_type_t : uint8_t { + CREDENTIAL_ADDED = 0x00, + CREDENTIAL_MODIFIED = 0x01, + CREDENTIAL_DELETED = 0x02, + CREDENTIAL_UNCHANGED = 0x03, + RESPONSE_TO_GET = 0x04, + CREDENTIAL_ADD_REJECTED_LOCATION_OCCUPIED = 0x05, + CREDENTIAL_MODIFY_REJECTED_LOCATION_EMPTY = 0x06, + CREDENTIAL_DUPLICATE_ERROR = 0x07, + CREDENTIAL_MANUFACTURER_SECURITY_RULE = 0x08, + CREDENTIAL_LOCATION_ALREADY_ASSIGNED = 0x09, + CREDENTIAL_DUPLICATE_ADMIN_CODE = 0x0A +}; + +sl_status_t + handle_credential_deletion(attribute_store::attribute& endpoint_node, + attribute_store::attribute& user_id_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_user_unique_id_t credential_slot) +{ + if (user_id != 0 && credential_type != 0 && credential_slot != 0) { + sl_log_info(LOG_TAG, + "Credential Deleted. Type %s, Slot %d (User %d)", + get_credential_type_debug_str(credential_type).c_str(), + credential_slot, + user_id); + // Delete the credential slot node + get_credential_identifier_nodes(endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, REPORTED_ATTRIBUTE}, + {credential_slot, REPORTED_ATTRIBUTE}) + .slot_node.delete_node(); + } else if (user_id != 0 && credential_type != 0 && credential_slot == 0) { + sl_log_info(LOG_TAG, + "All credential type %s deleted for user %d.", + get_credential_type_debug_str(credential_type).c_str(), + user_id); + for_each_credential_type_nodes_for_user( + user_id_node, + [](attribute_store::attribute &credential_type_node) { + credential_type_node.delete_node(); + }, + credential_type); + } else if (user_id != 0 && credential_type == 0 && credential_slot == 0) { + sl_log_info(LOG_TAG, "All credentials for user %d deleted.", user_id); + for_each_credential_type_nodes_for_user( + user_id_node, + [](attribute_store::attribute &credential_type_node) { + credential_type_node.delete_node(); + }); + } else if (user_id == 0 && credential_type == 0 && credential_slot == 0) { + sl_log_info(LOG_TAG, "All credentials deleted."); + for_each_credential_type_nodes( + endpoint_node, + [](attribute_store::attribute &credential_type_node) { + credential_type_node.delete_node(); + }); + } else if (user_id == 0 && credential_type != 0 && credential_slot == 0) { + sl_log_info(LOG_TAG, + "All credentials of type %s are deleted", + get_credential_type_debug_str(credential_type).c_str()); + for_each_credential_type_nodes( + endpoint_node, + [](attribute_store::attribute &credential_type_node) { + credential_type_node.delete_node(); + }, + credential_type); + } else { + sl_log_critical(LOG_TAG, + "Invalid combination of user_id %d, credential_type %s and " + "credential_slot %d for credential deletion", + user_id, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_credential_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Report"); + + attribute_store::attribute endpoint_node( + zwave_command_class_get_endpoint_node(connection_info)); + + const uint8_t min_size = 15; + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(min_size, UINT8_MAX)) { + sl_log_error(LOG_TAG, "Invalid frame size for Credential Report frame"); + return SL_STATUS_FAIL; + } + + credential_report_type_t credential_report_type + = static_cast(parser.read_byte()); + auto user_id = parser.read_sequential(2); + user_credential_type_t credential_type = parser.read_byte(); + auto credential_slot = parser.read_sequential(2); + + sl_log_debug(LOG_TAG, + "Credential Report (%d). %s, Slot %d (User %d)", + credential_report_type, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot, + user_id); + + // Helper function to clean up pending credentials slot nodes + auto clean_up_pending_credentials_slot_nodes = [&]() { + try { + auto nodes = get_credential_identifier_nodes( + endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, DESIRED_OR_REPORTED_ATTRIBUTE}, + {credential_slot, DESIRED_ATTRIBUTE}); + + nodes.slot_node.delete_node(); + sl_log_debug(LOG_TAG, + "Cleaning temporary credential slot node : %d (credential " + "type %s, user %d)", + credential_slot, + get_credential_type_debug_str(credential_type).c_str(), + user_id); + } catch (...) { + // Try again with reported attribute + // That should not trigger an error, but if it does it means that something went wrong + auto nodes = get_credential_identifier_nodes( + endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, DESIRED_OR_REPORTED_ATTRIBUTE}, + {credential_slot, REPORTED_ATTRIBUTE}); + + sl_log_debug( + LOG_TAG, + "Cleaning desired values of credential slot node : %d (credential " + "type %s, user %d)", + credential_slot, + get_credential_type_debug_str(credential_type).c_str(), + user_id); + + for (auto child: nodes.slot_node.children()) { + child.clear_desired(); + } + } + }; + + // We should have a valid user id if we receive this report + auto user_id_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + + attribute_store::attribute credential_type_node; + attribute_store::attribute credential_slot_node; + + switch (credential_report_type) { + case credential_report_type_t::CREDENTIAL_ADDED: + // In case of credential learn, the credential is already present in the + // node tree. So we don't check if the node exists before creating it. + // Only update existing nodes if they are present. + credential_type_node + = create_or_update_desired_value(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + credential_type); + credential_slot_node + = create_or_update_desired_value(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot); + break; + case credential_report_type_t::CREDENTIAL_MODIFIED: { + // Should throw an exception if the credential doesn't exists + auto nodes = get_credential_identifier_nodes( + endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, REPORTED_ATTRIBUTE}, + {credential_slot, REPORTED_ATTRIBUTE}); + credential_type_node = nodes.type_node; + credential_slot_node = nodes.slot_node; + // Clear desired value + credential_slot_node.clear_desired(); + credential_slot_node.set_reported(credential_slot); + } break; + case credential_report_type_t::CREDENTIAL_DELETED: + return handle_credential_deletion(endpoint_node, + user_id_node, + user_id, + credential_type, + credential_slot); + case credential_report_type_t::CREDENTIAL_UNCHANGED: + send_message_to_mqtt(SL_LOG_INFO, + "Credential Unchanged. Type " + + get_credential_type_debug_str(credential_type) + + ", Slot " + std::to_string(credential_slot) + + " (User " + std::to_string(user_id) + ")"); + return SL_STATUS_OK; + // Update desired value if found, otherwise create the nodes + case credential_report_type_t::RESPONSE_TO_GET: + // First check if this is the first credential interview + credential_type_node + = user_id_node.child_by_type_and_value(ATTRIBUTE(CREDENTIAL_TYPE), + 0, + REPORTED_ATTRIBUTE); + credential_slot_node = credential_type_node.child_by_type_and_value( + ATTRIBUTE(CREDENTIAL_SLOT), + 0, + DESIRED_ATTRIBUTE); + // Update the values of the first nodes if present + if (credential_type_node.is_valid() + && credential_slot_node.is_valid()) { + // If no credential are reported, we can delete the nodes + if (credential_type == 0 && credential_slot == 0) { + sl_log_debug(LOG_TAG, "No credential to get for user %d", user_id); + credential_type_node.delete_node(); + credential_slot_node.delete_node(); + return SL_STATUS_OK; + } else { + sl_log_debug(LOG_TAG, + "First credential : Updating credential type and slot " + "for user %d", + user_id); + credential_type_node.set_reported(credential_type); + credential_slot_node.clear_desired(); + credential_slot_node.set_reported(credential_slot); + } + } else { + // Otherwise create or get the nodes + credential_type_node + = create_or_update_desired_value(user_id_node, + ATTRIBUTE(CREDENTIAL_TYPE), + credential_type); + credential_slot_node + = create_or_update_desired_value(credential_type_node, + ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot); + } + break; + case credential_report_type_t::CREDENTIAL_ADD_REJECTED_LOCATION_OCCUPIED: + sl_log_error(LOG_TAG, + "Credential data rejected as it already exists : user %d, " + "credential type %s, credential slot %d", + user_id, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + clean_up_pending_credentials_slot_nodes(); + return SL_STATUS_OK; + case credential_report_type_t::CREDENTIAL_MODIFY_REJECTED_LOCATION_EMPTY: + sl_log_error( + LOG_TAG, + "Credential data cannot be modified as it does not exists : user %d, " + "credential type %s, credential slot %d", + user_id, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + + credential_type_node + = user_id_node.child_by_type_and_value(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type, + DESIRED_OR_REPORTED_ATTRIBUTE); + + if (!credential_type_node.is_valid()) { + sl_log_debug( + LOG_TAG, + "No credential type found for user %d, credential type %s", + user_id, + get_credential_type_debug_str(credential_type).c_str()); + return SL_STATUS_OK; + } + + credential_slot_node = credential_type_node.child_by_type_and_value( + ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + DESIRED_ATTRIBUTE); + + credential_slot_node.delete_node(); + return SL_STATUS_OK; + // Duplicate Credential : 0x02 + case credential_report_type_t::CREDENTIAL_DUPLICATE_ERROR: { + // Do nothing, the credential GET will clean up for us + sl_log_warning(LOG_TAG, + "Duplicate Credential (Already present for user %d, " + "credential type %s, " + "credential slot %d)", + user_id, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + + // So this is the fun part when we hunt down the faulty credential slot node + parser.read_byte(); // We don't care about this one + uint8_t cred_data_size = parser.read_byte(); + auto duplicate_data + = parser.read_sequential>(cred_data_size); + + bool found_duplicate = false; + // We need to find the credential slot node that contains the same data + for_each_credential_type_nodes( + endpoint_node, + [&found_duplicate, &duplicate_data]( + attribute_store::attribute ¤t_credential_type_node) { + for (auto ¤t_credential_slot_node: + current_credential_type_node.children( + ATTRIBUTE(CREDENTIAL_SLOT))) { + if (current_credential_slot_node.desired_exists()) { + auto current_data + = current_credential_slot_node + .child_by_type(ATTRIBUTE(CREDENTIAL_DATA)) + .get>(DESIRED_OR_REPORTED_ATTRIBUTE); + if ( + current_data + == duplicate_data) { //NOSONAR - Don't have a better way to write this + sl_log_debug(LOG_TAG, + "Found the faulty credential slot node : %d", + current_credential_slot_node + .desired()); + current_credential_slot_node.delete_node(); + found_duplicate = true; + return; + } + } + } + }, + credential_type); + + if (!found_duplicate) { + // If we are here that means we din't find the duplicate data + sl_log_error(LOG_TAG, + "Couldn't find the duplicate credential slot node."); + return SL_STATUS_FAIL; + } else { + return SL_STATUS_OK; + } + } + case credential_report_type_t::CREDENTIAL_MANUFACTURER_SECURITY_RULE: + sl_log_warning( + LOG_TAG, + "Credential data rejected as it doesn't respect manufacturer " + "security rules : user %d, credential type %s, " + "credential slot %d", + user_id, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + // This should contains the faulty credential + clean_up_pending_credentials_slot_nodes(); + return SL_STATUS_OK; + case credential_report_type_t::CREDENTIAL_LOCATION_ALREADY_ASSIGNED: + sl_log_warning( + LOG_TAG, + "Credential data rejected as location is already assigned : user %d, " + "credential type %s, credential slot %d", + user_id, + get_credential_type_debug_str(credential_type).c_str(), + credential_slot); + // This should contains the faulty credential + clean_up_pending_credentials_slot_nodes(); + return SL_STATUS_OK; + case credential_report_type_t::CREDENTIAL_DUPLICATE_ADMIN_CODE: + sl_log_warning(LOG_TAG, + "Credential data rejected as the new credential is the " + "same as admin code"); + // This should contains the faulty credential + clean_up_pending_credentials_slot_nodes(); + break; + default: + sl_log_error(LOG_TAG, + "Invalid credential report type %d", + credential_report_type); + return SL_STATUS_FAIL; + } + + if (!credential_type_node.is_valid()) { + sl_log_critical(LOG_TAG, + "Credential type is invalid when it should be. Can't " + "process credential report."); + return SL_STATUS_FAIL; + } + + if (!credential_slot_node.is_valid()) { + sl_log_critical(LOG_TAG, + "Credential slot is invalid when it should be. Can't " + "process credential report."); + return SL_STATUS_FAIL; + } + + // If we are here it means that we have a valid credential type and slot node + parser.read_byte_with_bitmask( + {CREDENTIAL_REPORT_PROPERTIES1_CRB_BIT_MASK, + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_READ_BACK))}); + + uint8_t cred_data_size = parser.read_byte(); + parser.read_sequential>( + cred_data_size, + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA))); + parser.read_byte( + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE))); + parser.read_sequential( + 2, + credential_slot_node.emplace_node( + ATTRIBUTE(CREDENTIAL_MODIFIER_NODE_ID))); + + // Next + user_credential_type_t next_credential_type = parser.read_byte(); + auto next_credential_slot + = parser.read_sequential(2); + + // Interview next credential is available + if (next_credential_type != 0 && next_credential_slot != 0 + && credential_report_type + == credential_report_type_t::RESPONSE_TO_GET) { + trigger_get_credential(user_id_node, + next_credential_type, + next_credential_slot); + } else { + sl_log_debug(LOG_TAG, "No more credential to get."); + // Trigger the next user interview if any + users_interview_state::trigger_get_for_next_user(endpoint_node); + } + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing Credential Report frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// Credential Learn Start/Report/Stop +///////////////////////////////////////////////////////////////////////////// +static sl_status_t zwave_command_class_user_credential_credential_learn_start( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Learn Start"); + attribute_store::attribute credential_operation_type_node(node); + + try { + frame_generator.initialize_frame(CREDENTIAL_LEARN_START, + frame, + sizeof(ZW_CREDENTIAL_LEARN_START_FRAME)); + auto nodes + = get_credential_identifier_nodes(credential_operation_type_node); + + frame_generator.add_value(nodes.user_unique_id_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(nodes.type_node, DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(nodes.slot_node, DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(credential_operation_type_node, + DESIRED_ATTRIBUTE); + frame_generator.add_value( + nodes.slot_node.child_by_type(ATTRIBUTE(CREDENTIAL_LEARN_TIMEOUT)), + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating Credential Learn Start frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +static sl_status_t zwave_command_class_user_credential_credential_learn_cancel( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Learn Cancel"); + attribute_store::attribute credential_learn_stop_node(node); + + credential_learn_stop_node.set_reported(1); + credential_learn_stop_node.clear_desired(); + + return frame_generator.generate_no_args_frame(CREDENTIAL_LEARN_CANCEL, + frame, + frame_length); +} + +sl_status_t zwave_command_class_user_credential_credential_learn_status_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + attribute_store::attribute endpoint_node + = zwave_command_class_get_endpoint_node(connection_info); + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(sizeof(ZW_CREDENTIAL_LEARN_REPORT_FRAME))) { + sl_log_error( + LOG_TAG, + "Invalid frame size for Credential Learn Status Report frame"); + return SL_STATUS_NOT_SUPPORTED; + } + + // Parse the frame + const uint8_t learn_status = parser.read_byte(); + const auto user_id + = parser.read_sequential(2); + const user_credential_type_t credential_type = parser.read_byte(); + const auto credential_slot + = parser.read_sequential(2); + const uint8_t step_remaining = parser.read_byte(); + + sl_log_debug(LOG_TAG, + "Credential Learn Status Report. Credential Type: %s / " + "Credential Slot: %d (User %d)", + cred_type_get_enum_value_name(credential_type).c_str(), + credential_slot, + user_id); + + auto credential_id_nodes = get_credential_identifier_nodes( + endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, DESIRED_OR_REPORTED_ATTRIBUTE}, + {credential_slot, DESIRED_OR_REPORTED_ATTRIBUTE}); + + // Get operation type so we can handle error cases + // We use desired or reported here since it can be set to reported by the + // supervision process. + auto operation_type + = credential_id_nodes.slot_node + .child_by_type(ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE)) + .desired_or_reported(); + + // Action based of current learn status + std::string learn_status_str; + bool need_deletion = false; + sl_log_level_t log_level = SL_LOG_INFO; + + switch (learn_status) { + case CREDENTIAL_LEARN_REPORT_STARTED: + learn_status_str = "Credential Learn Started"; + break; + case CREDENTIAL_LEARN_REPORT_SUCCESS: + learn_status_str = "Credential Learn Success"; + break; + case CREDENTIAL_LEARN_REPORT_ALREADY_IN_PROGRESS: + log_level = SL_LOG_WARNING; + learn_status_str = "Credential Learn already in progress"; + break; + case CREDENTIAL_LEARN_REPORT_ENDED_NOT_DUE_TO_TIMEOUT: + log_level = SL_LOG_ERROR; + learn_status_str = "Credential Learn Ended (not due to timeout)"; + need_deletion = (operation_type == USER_CREDENTIAL_OPERATION_TYPE_ADD); + break; + case CREDENTIAL_LEARN_REPORT_TIMEOUT: + log_level = SL_LOG_ERROR; + learn_status_str = "Credential Learn Timeout"; + need_deletion = (operation_type == USER_CREDENTIAL_OPERATION_TYPE_ADD); + break; + case 0x05: // Credential Learn Step Retry + learn_status_str = "Credential Learn Step Needs a Retry"; + need_deletion = (operation_type == USER_CREDENTIAL_OPERATION_TYPE_ADD); + break; + case CREDENTIAL_LEARN_REPORT_INVALID_CREDENTIAL_LEARN_ADD_OPERATION_TYPE: + log_level = SL_LOG_ERROR; + learn_status_str = "Invalid Add Operation Types"; + break; + case CREDENTIAL_LEARN_REPORT_INVALID_CREDENTIAL_LEARN_MODIFY_OPERATION_TYPE: + log_level = SL_LOG_ERROR; + learn_status_str = "Invalid Modify Operation Type"; + need_deletion = (operation_type == USER_CREDENTIAL_OPERATION_TYPE_ADD); + break; + default: + learn_status_str + = "Unknown Credential Learn Status " + std::to_string(learn_status); + log_level = SL_LOG_CRITICAL; + } + + auto message = boost::format("Credential Learn Status Report : %1% for " + "Credential Type %2% (Slot %3%, User %4%)") + % learn_status_str + % cred_type_get_enum_value_name(credential_type) + % credential_slot % user_id; + send_message_to_mqtt(log_level, message.str()); + + if (need_deletion) { + credential_id_nodes.slot_node.delete_node(); + return SL_STATUS_OK; + } + + // Update nodes + credential_id_nodes.slot_node.emplace_node( + ATTRIBUTE(CREDENTIAL_LEARN_STEPS_REMAINING), + step_remaining); + credential_id_nodes.slot_node.emplace_node( + ATTRIBUTE(CREDENTIAL_LEARN_STATUS), + learn_status); + + } catch (const std::exception &e) { + sl_log_error( + LOG_TAG, + "Error while parsing Credential Learn Status Report frame : %s", + e.what()); + + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// User Unique Identifier Credential Association Set/Report +///////////////////////////////////////////////////////////////////////////// + +static sl_status_t zwave_command_class_user_credential_uuic_association_set( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, + "User Unique Identifier Credential Association Set command"); + attribute_store::attribute destination_credential_slot_node(node); + + try { + frame_generator.initialize_frame( + USER_CREDENTIAL_ASSOCIATION_SET, + frame, + sizeof(ZW_USER_CREDENTIAL_ASSOCIATION_SET_FRAME)); + + auto nodes + = get_credential_identifier_nodes(destination_credential_slot_node); + frame_generator.add_value(nodes.user_unique_id_node, REPORTED_ATTRIBUTE); + frame_generator.add_value(nodes.type_node, REPORTED_ATTRIBUTE); + frame_generator.add_value(nodes.slot_node, REPORTED_ATTRIBUTE); + frame_generator.add_value( + nodes.slot_node.child_by_type(ATTRIBUTE(ASSOCIATION_DESTINATION_USER_ID)), + DESIRED_ATTRIBUTE); + frame_generator.add_value(destination_credential_slot_node, + DESIRED_ATTRIBUTE); + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating User Unique Identifier Credential " + "Association Set frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_uuic_association_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_log_debug(LOG_TAG, "UUIC Association Report"); + + attribute_store::attribute endpoint_node( + zwave_command_class_get_endpoint_node(connection_info)); + + const uint8_t expected_size + = sizeof(ZW_USER_CREDENTIAL_ASSOCIATION_REPORT_FRAME); + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(expected_size)) { + sl_log_error(LOG_TAG, + "Invalid frame size for UUIC Association Report frame"); + return SL_STATUS_FAIL; + } + + // Parse the frame + const auto source_user_id + = parser.read_sequential(2); + const user_credential_type_t source_credential_type = parser.read_byte(); + const auto source_credential_slot + = parser.read_sequential(2); + const auto destination_user_id + = parser.read_sequential(2); + const auto destination_credential_slot + = parser.read_sequential(2); + const uint8_t association_status = parser.read_byte(); + + sl_log_debug(LOG_TAG, + "User Unique Identifier Credential Association Report."); + sl_log_debug(LOG_TAG, "\tSource User ID: %d", source_user_id); + sl_log_debug(LOG_TAG, + "\tSource Credential Type: %d", + source_credential_type); + sl_log_debug(LOG_TAG, + "\tSource Credential Slot: %d", + source_credential_slot); + sl_log_debug(LOG_TAG, "\tDestination User ID: %d", destination_user_id); + sl_log_debug(LOG_TAG, + "\tDestination Credential Slot: %d", + destination_credential_slot); + + // Get nodes + auto source_credential_nodes = get_credential_identifier_nodes( + endpoint_node, + {source_user_id, REPORTED_ATTRIBUTE}, + {source_credential_type, REPORTED_ATTRIBUTE}, + {source_credential_slot, REPORTED_ATTRIBUTE}); + + // Set association status + auto source_credential_slot_node = source_credential_nodes.slot_node; + source_credential_slot_node.emplace_node(ATTRIBUTE(ASSOCIATION_STATUS)) + .set_reported(association_status); + + // Clean up association data so ZPC won't try to send the SET command again + std::vector attributes_to_be_deleted + = {ATTRIBUTE(ASSOCIATION_DESTINATION_USER_ID), + ATTRIBUTE(ASSOCIATION_DESTINATION_CREDENTIAL_SLOT)}; + for (auto attribute_type: attributes_to_be_deleted) { + source_credential_slot_node.child_by_type(attribute_type).delete_node(); + } + + // If something went wrong end device side, log the error and return + // This should handle the slot already taken case + if (association_status != USER_CREDENTIAL_ASSOCIATION_REPORT_SUCCESS) { + send_message_to_mqtt( + SL_LOG_ERROR, + "User Unique Identifier Credential Association error. " + "Reported status code : " + + std::to_string(association_status)); + return SL_STATUS_OK; + } + + send_message_to_mqtt( + SL_LOG_INFO, + (boost::format("Credential Slot %1% (%2%) (user %3%) moved to " + "Credential slot %4% (user %5%)") + % source_credential_slot + % cred_rule_get_enum_value_name(source_credential_type) % source_user_id + % destination_credential_slot % destination_user_id) + .str()); + + source_credential_slot_node.set_reported(destination_credential_slot); + + // Need to move to new user + if (destination_user_id != source_user_id) { + sl_log_debug(LOG_TAG, "Moving slot to new user"); + + // Get destination user node + auto destination_user_id_node + = get_user_unique_id_node(endpoint_node, + destination_user_id, + REPORTED_ATTRIBUTE); + + // Get new parent + auto destination_credential_type_node + = destination_user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), + source_credential_type); + + sl_status_t result = source_credential_slot_node.change_parent( + destination_credential_type_node); + if (result != SL_STATUS_OK) { + send_message_to_mqtt( + SL_LOG_ERROR, + (boost::format( + "Error while moving slot %1% (user %2%) to slot %3% (user %4%)") + % source_credential_slot % source_user_id + % destination_credential_slot % destination_user_id) + .str()); + return result; + } + } + + // Call MQTT callback if needed to notify that the slot has changed + for (auto &uicc_slot_changed_callback: + user_credential_slot_changed_callback) { + uicc_slot_changed_callback( + {source_user_id, source_credential_type, source_credential_slot}, + source_credential_slot_node); + } + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing UUIC Association Report frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// User Set/Get/Report +///////////////////////////////////////////////////////////////////////////// + +static sl_status_t zwave_command_class_user_credential_user_set( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + try { + // Node setup + attribute_store::attribute user_operation_type_node(node); + attribute_store::attribute user_unique_id_node + = user_operation_type_node.first_parent(ATTRIBUTE(USER_UNIQUE_ID)); + + // Get Values + auto user_unique_id + = user_unique_id_node + .desired_or_reported(); + auto user_operation_type + = user_operation_type_node.desired(); + + const bool is_delete_operation + = (user_operation_type == USER_SET_OPERATION_TYPE_DELETE); + + uint8_t expected_frame_size = is_delete_operation ? 5 : 12; + uint8_t user_name_size = 0; + + if (!is_delete_operation) { + user_name_size = static_cast( + user_unique_id_node.child_by_type(ATTRIBUTE(USER_NAME)) + .get(DESIRED_OR_REPORTED_ATTRIBUTE) + .size()); + } + + // Append the user name size (will be 0 if is delete operation) + expected_frame_size += user_name_size; + + sl_log_debug(LOG_TAG, + "User SET for user %d (operation type : %d)", + user_unique_id, + user_operation_type); + + // Creating the frame + frame_generator.initialize_frame(USER_SET, frame, expected_frame_size); + + frame_generator.add_value(user_operation_type_node, DESIRED_ATTRIBUTE); + frame_generator.add_value(user_unique_id_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + + if (!is_delete_operation) { + frame_generator.add_value( + user_unique_id_node.child_by_type(ATTRIBUTE(USER_TYPE)), + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value( + user_unique_id_node.child_by_type(ATTRIBUTE(USER_ACTIVE_STATE)), + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value( + user_unique_id_node.child_by_type(ATTRIBUTE(CREDENTIAL_RULE)), + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value(user_unique_id_node.child_by_type( + ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES)), + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_value( + user_unique_id_node.child_by_type(ATTRIBUTE(USER_NAME_ENCODING)), + DESIRED_OR_REPORTED_ATTRIBUTE); + frame_generator.add_raw_byte(user_name_size); + frame_generator.add_value( + user_unique_id_node.child_by_type(ATTRIBUTE(USER_NAME)), + DESIRED_OR_REPORTED_ATTRIBUTE); + } + + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating User SET frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + return SL_STATUS_OK; +} + +static sl_status_t zwave_command_class_user_credential_user_get( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + attribute_store::attribute user_unique_id_node(node); + + // If we enter this state it means that something went badly wrong or + // user initiate the interview process again. + // In both cases we want to invalidate the user database so that the device + // can send us the correct user database. + + if (!user_unique_id_node.desired_exists()) { + sl_log_warning(LOG_TAG, + "Can't get user unique id Desired value. Removing all users " + "to perform interview again."); + attribute_store::attribute endpoint_node = user_unique_id_node.parent(); + + // Get User node count + for (auto user_node: endpoint_node.children(ATTRIBUTE(USER_UNIQUE_ID))) { + attribute_store_delete_node(user_node); + } + + // NOTE : In the case of user re-interviewing the device, it will be interviewed again when the node goes ONLINE. + return SL_STATUS_NOT_SUPPORTED; + } + + user_credential_user_unique_id_t user_id + = user_unique_id_node.desired(); + sl_log_debug(LOG_TAG, "User Get for user %d", user_id); + + // Generate the frame + constexpr uint8_t expected_frame_size + = static_cast(sizeof(ZW_USER_GET_FRAME)); + try { + frame_generator.initialize_frame(USER_GET, frame, expected_frame_size); + frame_generator.add_value(user_unique_id_node, DESIRED_ATTRIBUTE); + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating USER_GET frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + + // This special user ID will contains the unaffected credentials. + if (user_id == 0) { + users_interview_state::set_user_0_node(user_unique_id_node); + } + + return SL_STATUS_OK; +} + +// TODO : Update with values in ZW_cmdclass.h +enum class user_report_type_t : uint8_t { + USER_ADDED = 0x00, + USER_MODIFIED = 0x01, + USER_DELETED = 0x02, + USER_UNCHANGED = 0x03, + RESPONSE_TO_GET = 0x04, + USER_ADD_REJECTED_LOCATION_OCCUPIED = 0x05, + USER_MODIFY_REJECTED_LOCATION_EMPTY = 0x06, + NON_ZERO_EXPIRING_MINUTES_INVALID = 0x07 +}; + +sl_status_t zwave_command_class_user_credential_user_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_log_debug(LOG_TAG, "User Report"); + + attribute_store::attribute endpoint_node( + zwave_command_class_get_endpoint_node(connection_info)); + + // Resolve user 0 node if needed + // We need to do that here so that the attribute store mark this node as resolved + users_interview_state::resolve_user_0_node(); + + const uint8_t expected_min_size = 16; + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(expected_min_size, UINT8_MAX)) { + sl_log_error(LOG_TAG, "Invalid frame size for User Report frame"); + return SL_STATUS_FAIL; + } + + auto user_report_type = static_cast(parser.read_byte()); + + auto next_user_id + = parser.read_sequential(2); + + user_credential_modifier_type_t user_modifier_type = parser.read_byte(); + auto user_modifier_id + = parser.read_sequential(2); + + // Get User ID + auto current_user_id + = parser.read_sequential(2); + + sl_log_debug(LOG_TAG, + "User report for user %d. User report type %d", + current_user_id, + user_report_type); + + // CC:0083.01.05.11.006: Zero is an invalid User Unique Identifier and MUST NOT be used by the node + if (current_user_id == 0) { + if (user_report_type == user_report_type_t::RESPONSE_TO_GET) { + sl_log_info(LOG_TAG, "No users was found on the device."); + return SL_STATUS_OK; + } else if (user_report_type == user_report_type_t::USER_DELETED) { + sl_log_info(LOG_TAG, "Request to delete all users"); + + for (auto user_node: + endpoint_node.children(ATTRIBUTE(USER_UNIQUE_ID))) { + // Don't delete special user 0 + if (user_node.reported_exists() + && user_node.reported() == 0) { //NOSONAR - Don't have a better way to write this + continue; + } + + attribute_store_delete_node(user_node); + } + + return SL_STATUS_OK; + } else { + sl_log_error(LOG_TAG, + "User report with ID 0 received. This is an invalid User " + "Unique Identifier and MUST NOT be used by the node."); + return SL_STATUS_FAIL; + } + } + + // Lambda function to remove user node in an invalid state + auto remove_current_user_node = [&]() { + get_user_unique_id_node(endpoint_node, current_user_id, DESIRED_ATTRIBUTE) + .delete_node(); + }; + + // Current user id node that will be used later + // Each report type has a different behavior + attribute_store::attribute current_user_id_node; + switch (user_report_type) { + // In either case we want to create the user node if it doesn't exists + // or update the desired value if it does + case user_report_type_t::USER_ADDED: + case user_report_type_t::RESPONSE_TO_GET: + current_user_id_node + = create_or_update_desired_value(endpoint_node, + ATTRIBUTE(USER_UNIQUE_ID), + current_user_id); + break; + // We should have a record of given user ID + case user_report_type_t::USER_MODIFIED: + case user_report_type_t::USER_DELETED: + current_user_id_node = get_user_unique_id_node(endpoint_node, + current_user_id, + REPORTED_ATTRIBUTE); + break; + // Special/Errors cases + case user_report_type_t::USER_UNCHANGED: + sl_log_info(LOG_TAG, "User %d is unchanged", current_user_id); + return SL_STATUS_OK; + case user_report_type_t::USER_ADD_REJECTED_LOCATION_OCCUPIED: + sl_log_warning(LOG_TAG, + "User %d was not added since it already exists. Try to " + "modify it instead.", + current_user_id); + remove_current_user_node(); + return SL_STATUS_OK; + case user_report_type_t::USER_MODIFY_REJECTED_LOCATION_EMPTY: + sl_log_warning(LOG_TAG, + "User %d was not modified since it doesn't exists. Try " + "to add it instead.", + current_user_id); + remove_current_user_node(); + return SL_STATUS_OK; + case user_report_type_t::NON_ZERO_EXPIRING_MINUTES_INVALID: + sl_log_warning(LOG_TAG, + "User %d was not modified/added since the expiring " + "timeout minutes is invalid.", + current_user_id); + return SL_STATUS_OK; + default: + sl_log_error(LOG_TAG, "Invalid value for user report type."); + return SL_STATUS_FAIL; + }; + + // Deleted special case + if (user_report_type == user_report_type_t::USER_DELETED) { + sl_log_info(LOG_TAG, "User %d has been deleted", current_user_id); + current_user_id_node.delete_node(); + return SL_STATUS_OK; + } + + // Set already parsed values + current_user_id_node.emplace_node(ATTRIBUTE(USER_MODIFIER_TYPE)) + .set_reported(user_modifier_type); + current_user_id_node.emplace_node(ATTRIBUTE(USER_MODIFIER_NODE_ID)) + .set_reported(user_modifier_id); + + // Keep parsing the frame + parser.read_byte(current_user_id_node.emplace_node(ATTRIBUTE(USER_TYPE))); + parser.read_byte_with_bitmask( + {USER_REPORT_PROPERTIES1_USER_ACTIVE_STATE_BIT_MASK, + current_user_id_node.emplace_node(ATTRIBUTE(USER_ACTIVE_STATE))}); + parser.read_byte( + current_user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_RULE))); + parser.read_sequential( + 2, + current_user_id_node.emplace_node( + ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES))); + parser.read_byte_with_bitmask( + {USER_REPORT_PROPERTIES2_USER_NAME_ENCODING_MASK, + current_user_id_node.emplace_node(ATTRIBUTE(USER_NAME_ENCODING))}); + parser.read_string(current_user_id_node.emplace_node(ATTRIBUTE(USER_NAME))); + + // Get credentials + trigger_get_credential(current_user_id_node, 0, 0); + + if (next_user_id != 0 + && user_report_type == user_report_type_t::RESPONSE_TO_GET) { + if (!user_exists(endpoint_node, next_user_id)) { + users_interview_state::schedule_next_user_interview(next_user_id); + } else { + sl_log_error(LOG_TAG, + "User %d already exists. Not discovering more users.", + next_user_id); + } + } else { + sl_log_debug(LOG_TAG, + "User %d is the last user to be discovered.", + current_user_id); + } + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing User Report frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// Checksum helpers +///////////////////////////////////////////////////////////////////////////// + +/** + * @brief Compte the checksum and verify the checksum integrity. + * + * Compare crc16 of checksum_data and expected checksum and put it in the + * checksum_error_type if not matching. + * + * @param base_node The base node to put the error attribute + * @param checksum_error_type The type of the error attribute + * @param checksum_data The data to compute the checksum. Checksum will be 0 if empty. + * @param expected_checksum The expected checksum + * + * @return SL_STATUS_OK if checksum is correct, SL_STATUS_FAIL otherwise +*/ +sl_status_t check_checksum_value(attribute_store::attribute base_node, + attribute_store_type_t checksum_error_type, + user_credential_checksum_t computed_checksum, + user_credential_checksum_t expected_checksum) +{ + sl_status_t status = SL_STATUS_FAIL; + + if (computed_checksum != expected_checksum) { + sl_log_error(LOG_TAG, + "Checksum mismatch (%s). Expected 0x%X, got 0x%X", + base_node.value_to_string().c_str(), + expected_checksum, + computed_checksum); + base_node.emplace_node(checksum_error_type).set_reported(computed_checksum); + } else { + // If we don't have any errors we remove the checksum_error_type node + base_node.child_by_type(checksum_error_type).delete_node(); + status = SL_STATUS_OK; + } + + return status; +} + +///////////////////////////////////////////////////////////////////////////// +// User Checksum Get/Report +///////////////////////////////////////////////////////////////////////////// +static sl_status_t zwave_command_class_user_credential_user_checksum_get( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "User Checksum Get"); + attribute_store::attribute checksum_node(node); + + auto user_id_node = checksum_node.first_parent(ATTRIBUTE(USER_UNIQUE_ID)); + + if (!user_id_node.is_valid()) { + sl_log_error( + LOG_TAG, + "Can't find User Unique ID node. Not sending User Checksum Get."); + return SL_STATUS_NOT_SUPPORTED; + } + + constexpr uint8_t expected_frame_size + = static_cast(sizeof(ZW_USER_CHECKSUM_GET_FRAME)); + + try { + frame_generator.initialize_frame(USER_CHECKSUM_GET, + frame, + expected_frame_size); + frame_generator.add_value(user_id_node); + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating User Checksum Get frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_user_checksum_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_status_t result = SL_STATUS_FAIL; + + constexpr uint8_t expected_frame_length + = sizeof(ZW_USER_CHECKSUM_REPORT_FRAME); + + attribute_store::attribute endpoint_node + = zwave_command_class_get_endpoint_node(connection_info); + + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(expected_frame_length)) { + sl_log_error(LOG_TAG, + "Invalid frame size for User Checksum Report frame"); + return SL_STATUS_NOT_SUPPORTED; + } + + // Parse the frame + const auto user_id + = parser.read_sequential(2); + const auto user_checksum + = parser.read_sequential(2); + + sl_log_debug(LOG_TAG, + "User Checksum Report. Source User ID: %d / " + "Checksum: 0x%X", + user_id, + user_checksum); + + auto user_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + + // Compute checksum ourselves to see if it matches + user_credential::checksum_calculator checksum_calculator; + add_user_node_to_checksum(user_node, checksum_calculator); + + result = check_checksum_value(user_node, + ATTRIBUTE(USER_CHECKSUM_MISMATCH_ERROR), + checksum_calculator.compute_checksum(), + user_checksum); + + user_node.emplace_node(ATTRIBUTE(USER_CHECKSUM)) + .set_reported(user_checksum); + + if (result == SL_STATUS_OK) { + send_message_to_mqtt(SL_LOG_INFO, + "User Checksum for user " + std::to_string(user_id) + + " is correct."); + } else { + send_message_to_mqtt(SL_LOG_ERROR, + "Mismatch User Checksum for user " + + std::to_string(user_id)); + } + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing User Checksum Report frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return result; +} + +///////////////////////////////////////////////////////////////////////////// +// Credential Checksum Get/Report +///////////////////////////////////////////////////////////////////////////// + +static sl_status_t zwave_command_class_user_credential_credential_checksum_get( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Credential Checksum Get"); + + attribute_store::attribute credential_checksum_node(node); + try { + auto credential_type_node = credential_checksum_node.first_parent( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE)); + + if (!credential_type_node.is_valid()) { + sl_log_error(LOG_TAG, + "Can't find Credential Type node. Not sending Credential " + "Checksum Get."); + return SL_STATUS_NOT_SUPPORTED; + } + + frame_generator.initialize_frame(CREDENTIAL_CHECKSUM_GET, + frame, + sizeof(ZW_CREDENTIAL_CHECKSUM_GET_FRAME)); + + frame_generator.add_value(credential_type_node, REPORTED_ATTRIBUTE); + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating Credential Checksum Get frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return SL_STATUS_OK; +} + +sl_status_t + zwave_command_class_user_credential_credential_checksum_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_status_t result = SL_STATUS_FAIL; + + attribute_store::attribute endpoint_node + = zwave_command_class_get_endpoint_node(connection_info); + + constexpr uint8_t expected_frame_length + = sizeof(ZW_CREDENTIAL_CHECKSUM_REPORT_FRAME); + try { + zwave_frame_parser parser(frame_data, frame_length); + + if (!parser.is_frame_size_valid(expected_frame_length)) { + sl_log_error(LOG_TAG, + "Invalid frame size for Credential Checksum Report frame"); + return SL_STATUS_NOT_SUPPORTED; + } + + // Parse the frame + const user_credential_type_t credential_type = parser.read_byte(); + const auto credential_checksum + = parser.read_sequential(2); + + sl_log_debug(LOG_TAG, + "Credential Checksum Report. Credential type: %d / " + "Checksum: 0x%X", + credential_type, + credential_checksum); + + // Get the credential type node + auto credential_type_node = endpoint_node.child_by_type_and_value( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + credential_type); + if (!credential_type_node.is_valid()) { + sl_log_error(LOG_TAG, + "Can't find Credential Type %s reported by Credential " + "Checksum Report", + get_credential_type_debug_str(credential_type).c_str()); + return SL_STATUS_FAIL; + } + + credential_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_CHECKSUM)) + .set_reported(credential_checksum); + + // Compute checksum ourselves to see if it matches + user_credential::checksum_calculator checksum_calculator; + for_each_credential_type_nodes( + endpoint_node, + [&checksum_calculator](auto current_credential_type_node) { + for (auto current_credential_slot_node: + current_credential_type_node.children( + ATTRIBUTE(CREDENTIAL_SLOT))) { + if (!current_credential_slot_node.reported_exists()) { + sl_log_debug( + LOG_TAG, + "%s reported value is not defined. Not adding to checksum.", + current_credential_slot_node.value_to_string()); + continue; + } + + checksum_calculator.add_node(current_credential_slot_node); + checksum_calculator.add_node( + current_credential_slot_node.child_by_type( + ATTRIBUTE(CREDENTIAL_DATA))); + } + }, + credential_type); + + result = check_checksum_value(credential_type_node, + ATTRIBUTE(CREDENTIAL_CHECKSUM_MISMATCH_ERROR), + checksum_calculator.compute_checksum(), + credential_checksum); + + if (result == SL_STATUS_OK) { + send_message_to_mqtt(SL_LOG_INFO, + "Credential Checksum for " + + cred_type_get_enum_value_name(credential_type) + + " is correct."); + } else { + send_message_to_mqtt(SL_LOG_ERROR, + "Mismatch Credential Checksum for " + + cred_type_get_enum_value_name(credential_type)); + } + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing Credential Checksum Report frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + + return result; +} + +///////////////////////////////////////////////////////////////////////////// +// Admin code Set/Get/Report +///////////////////////////////////////////////////////////////////////////// +static sl_status_t zwave_command_class_user_credential_admin_pin_code_set( + attribute_store_node_t node, uint8_t *frame, uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Admin PIN Code Set"); + + try { + // Node setup + attribute_store::attribute admin_pin_code_node(node); + + // Get Values + std::vector admin_pin_code + = admin_pin_code_node.desired>(); + + // This represents the case where the admin pin code is empty + // We need this workaround because attribute store doesn't support empty values as + // they are treated as non existing + if (is_admin_code_empty(admin_pin_code)) { + admin_pin_code.clear(); + } + + user_credential::credential_capabilities credential_capabilities( + admin_pin_code_node.first_parent(ATTRIBUTE_ENDPOINT_ID)); + + if (admin_pin_code.empty() + && !credential_capabilities.is_admin_code_deactivation_supported()) { + send_message_to_mqtt(SL_LOG_ERROR, + "Admin PIN code is empty and the device doesn't " + "support deactivation. Not sending Admin PIN code."); + return SL_STATUS_NOT_SUPPORTED; + } + + // 2 for header + // 1 for length + const uint8_t admin_code_size = static_cast(admin_pin_code.size()); + const uint8_t expected_frame_size = admin_code_size + 3; + + // Creating the frame + frame_generator.initialize_frame(ADMIN_PIN_CODE_SET, + frame, + expected_frame_size); + + // In every case we add 0 to the frame + frame_generator.add_raw_byte(admin_code_size); + + // Do not add anything to the frame if the admin pin code is empty + if (!admin_pin_code.empty()) { + frame_generator.add_value(admin_pin_code_node, + DESIRED_OR_REPORTED_ATTRIBUTE); + } + + frame_generator.validate_frame(frame_length); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while generating Admin PIN Code frame : %s", + e.what()); + return SL_STATUS_NOT_SUPPORTED; + } + return SL_STATUS_OK; +} + +static sl_status_t zwave_command_class_user_credential_admin_pin_code_get( + [[maybe_unused]] attribute_store_node_t node, + uint8_t *frame, + uint16_t *frame_length) +{ + sl_log_debug(LOG_TAG, "Admin PIN Code Get"); + // No definition yet for ADMIN_PIN_CODE_GET we use raw value + return frame_generator.generate_no_args_frame(ADMIN_PIN_CODE_GET, + frame, + frame_length); +} + +sl_status_t zwave_command_class_user_credential_admin_pin_code_handle_report( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + sl_log_debug(LOG_TAG, "Admin PIN Code Report"); + + attribute_store::attribute endpoint_node( + zwave_command_class_get_endpoint_node(connection_info)); + + const uint8_t min_size = 3; + + try { + zwave_frame_parser parser(frame_data, frame_length); + // 0xF since the size of the Admin PIN code is on 4 bits + if (!parser.is_frame_size_valid(min_size, min_size + 0xF)) { + sl_log_error(LOG_TAG, + "Invalid frame size for Admin PIN Code Report frame"); + return SL_STATUS_FAIL; + } + + // Parse the frame + constexpr uint8_t admin_code_op_result_bitmask = 0b11110000; + constexpr uint8_t admin_code_length_bitmask = 0b00001111; + // First parse the code size and operation result + auto result = parser.read_byte_with_bitmask( + {{admin_code_op_result_bitmask, + endpoint_node.emplace_node(ATTRIBUTE(ADMIN_PIN_CODE_OPERATION_RESULT))}, + {admin_code_length_bitmask}}); + + auto admin_code_op_result = result[admin_code_op_result_bitmask]; + switch (admin_code_op_result) { + case ADMIN_PIN_CODE_REPORT_MODIFIED: // Modified + break; + case ADMIN_PIN_CODE_REPORT_UNMODIFIED: // Unmodified + send_message_to_mqtt(SL_LOG_INFO, "Admin PIN code is unchanged."); + break; + case ADMIN_PIN_CODE_REPORT_RESPONSE_TO_GET: // Response to get + break; + case ADMIN_PIN_CODE_REPORT_DUPLICATE_CREDENTIAL: // Duplicate Credential + send_message_to_mqtt(SL_LOG_ERROR, + "Admin Code was not modified - a duplicate PIN " + "code exists in the Credential database."); + break; + case ADMIN_PIN_CODE_REPORT_MANUFACTURER_SECURITY_RULE: // Manufacturer Security Rule + send_message_to_mqtt(SL_LOG_ERROR, + "Admin Code was not modified as the provided code " + "fails a manufacturer security rule"); + break; + case ADMIN_PIN_CODE_REPORT_NOT_SUPPORTED: // Admin Code not supported + send_message_to_mqtt(SL_LOG_ERROR, + "Admin Code was not modified as the device does " + "not support Admin Code functionality."); + break; + case ADMIN_PIN_CODE_REPORT_DEACTIVATION_NOT_SUPPORTED: // Admin Code Deactivation not supported + send_message_to_mqtt( + SL_LOG_ERROR, + "Admin Code was not modified as the device does " + "not support Admin Code deactivation functionality."); + break; + case ADMIN_PIN_CODE_REPORT_UNSPECIFIED_ERROR: // Unspecified Node Error + send_message_to_mqtt( + SL_LOG_ERROR, + "Unknown issue with Get/Set Admin Code operation."); + break; + default: + send_message_to_mqtt(SL_LOG_ERROR, + "Admin PIN Code unknown Operation Result."); + return SL_STATUS_FAIL; + } + + // Modified or Response to get + if (admin_code_op_result == ADMIN_PIN_CODE_REPORT_RESPONSE_TO_GET + || admin_code_op_result == ADMIN_PIN_CODE_REPORT_MODIFIED) { + auto admin_code_size = result[admin_code_length_bitmask]; + sl_log_debug(LOG_TAG, "Admin PIN Code size : %d", admin_code_size); + + auto admin_pin_code_node + = endpoint_node.emplace_node(ATTRIBUTE(ADMIN_PIN_CODE)); + + if (admin_code_size != 0) { + parser.read_sequential>(admin_code_size, + admin_pin_code_node); + } else { + // Since set an empty vector is not supported we delete the node + sl_log_debug(LOG_TAG, "Admin PIN Code is empty."); + set_empty_admin_code(admin_pin_code_node, REPORTED_ATTRIBUTE); + } + } + + return SL_STATUS_OK; + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while parsing Admin Pin Report frame : %s", + e.what()); + return SL_STATUS_FAIL; + } + return SL_STATUS_OK; +} + +///////////////////////////////////////////////////////////////////////////// +// Post interview actions +///////////////////////////////////////////////////////////////////////////// +void zwave_network_status_changed(attribute_store_node_t node, + attribute_store_change_t change) +{ + // We englobe this in case we can't read an attribute or something goes wrong + try { + attribute_store::attribute network_status_node(node); + auto node_id_node = network_status_node.first_parent(ATTRIBUTE_NODE_ID); + + // Should not happen but we check anyway to prevent an exception to raise + if (!node_id_node.reported_exists()) { + return; + } + + auto node_id = node_id_node.reported(); + + // If we are updating the zpc node or if we trying to delete the attribute we don't want to do anything + if (change != ATTRIBUTE_UPDATED || get_zpc_node_id_node() == node_id_node) { + return; + } + + // In case we are not ready yet and don't have a reported value + if (!network_status_node.reported_exists()) { + return; + } + + // If the endpoint report is marked as ONLINE_FUNCTIONAL + if (network_status_node.reported() + == ZCL_NODE_STATE_NETWORK_STATUS_ONLINE_FUNCTIONAL) { + sl_log_debug(LOG_TAG, + "Node %d is now ONLINE_FUNCTIONAL : start the delayed " + "interview process", + node_id); + // Perform action on each endpoint that supports User Credential Command class + sl_log_debug(LOG_TAG, "Checking endpoints..."); + for (auto endpoint_node: node_id_node.children(ATTRIBUTE_ENDPOINT_ID)) { + auto endpoint_id = endpoint_node.reported(); + // Check if the endpoint supports User Credential Command class + if (!zwave_node_supports_command_class(COMMAND_CLASS_USER_CREDENTIAL, + node_id, + endpoint_id)) { + continue; + } + + sl_log_debug(LOG_TAG, + "Endpoint %d supports User Credential.", + endpoint_id); + auto user_count + = endpoint_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + if (user_count != 0) { + sl_log_debug(LOG_TAG, "Users already discovered. No actions needed."); + continue; + } + + sl_log_debug(LOG_TAG, + "No user found. Starting User and Credential interview"); + // Start the interview process with user ID = 0 + endpoint_node.add_node(ATTRIBUTE(USER_UNIQUE_ID)) + .set_desired(0); + } + sl_log_debug(LOG_TAG, "Done."); + } + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while handling network status change : %s", + e.what()); + } +} + +///////////////////////////////////////////////////////////////////////////// +// Class logic +///////////////////////////////////////////////////////////////////////////// + +// Control handler +sl_status_t zwave_command_class_user_credential_control_handler( + const zwave_controller_connection_info_t *connection_info, + const uint8_t *frame_data, + uint16_t frame_length) +{ + if (frame_length <= COMMAND_INDEX) { + return SL_STATUS_NOT_SUPPORTED; + } + + switch (frame_data[COMMAND_INDEX]) { + case USER_CAPABILITIES_REPORT: + return zwave_command_class_user_credential_user_capabilities_handle_report( + connection_info, + frame_data, + frame_length); + case CREDENTIAL_CAPABILITIES_REPORT: + return zwave_command_class_user_credential_credential_capabilities_handle_report( + connection_info, + frame_data, + frame_length); + case ALL_USERS_CHECKSUM_REPORT: + return zwave_command_class_user_credential_all_user_checksum_handle_report( + connection_info, + frame_data, + frame_length); + case USER_REPORT: + return zwave_command_class_user_credential_user_handle_report( + connection_info, + frame_data, + frame_length); + case CREDENTIAL_REPORT: + return zwave_command_class_user_credential_credential_handle_report( + connection_info, + frame_data, + frame_length); + case CREDENTIAL_LEARN_REPORT: + return zwave_command_class_user_credential_credential_learn_status_report( + connection_info, + frame_data, + frame_length); + case USER_CREDENTIAL_ASSOCIATION_REPORT: + return zwave_command_class_user_credential_uuic_association_report( + connection_info, + frame_data, + frame_length); + case USER_CHECKSUM_REPORT: + return zwave_command_class_user_credential_user_checksum_handle_report( + connection_info, + frame_data, + frame_length); + case CREDENTIAL_CHECKSUM_REPORT: + return zwave_command_class_user_credential_credential_checksum_handle_report( + connection_info, + frame_data, + frame_length); + case 0x1C: // ADMIN_PIN_CODE_REPORT + return zwave_command_class_user_credential_admin_pin_code_handle_report( + connection_info, + frame_data, + frame_length); + default: + return SL_STATUS_NOT_SUPPORTED; + } +} + +// Entry point +sl_status_t zwave_command_class_user_credential_init() +{ + attribute_store_register_callback_by_type( + &zwave_command_class_user_credential_on_version_attribute_update, + ATTRIBUTE(VERSION)); + + attribute_resolver_register_rule( + ATTRIBUTE(NUMBER_OF_USERS), + NULL, + &zwave_command_class_user_credential_user_capabilities_get); + + attribute_resolver_register_rule( + ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM), + NULL, + &zwave_command_class_user_credential_credential_capabilities_get); + + attribute_resolver_register_rule( + ATTRIBUTE(ALL_USERS_CHECKSUM), + NULL, + &zwave_command_class_user_credential_all_user_checksum_get); + + attribute_resolver_register_rule( + ATTRIBUTE(USER_UNIQUE_ID), + NULL, + &zwave_command_class_user_credential_user_get); + + attribute_resolver_register_rule( + ATTRIBUTE(USER_OPERATION_TYPE), + &zwave_command_class_user_credential_user_set, + NULL); + + attribute_resolver_register_rule( + ATTRIBUTE(CREDENTIAL_SLOT), + NULL, + &zwave_command_class_user_credential_credential_get); + + attribute_resolver_register_rule( + ATTRIBUTE(CREDENTIAL_OPERATION_TYPE), + &zwave_command_class_user_credential_credential_set, + NULL); + + attribute_resolver_register_rule( + ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE), + &zwave_command_class_user_credential_credential_learn_start, + NULL); + + attribute_resolver_register_rule( + ATTRIBUTE(CREDENTIAL_LEARN_STOP), + &zwave_command_class_user_credential_credential_learn_cancel, + NULL); + + attribute_resolver_register_rule( + ATTRIBUTE(ASSOCIATION_DESTINATION_CREDENTIAL_SLOT), + &zwave_command_class_user_credential_uuic_association_set, + NULL); + + attribute_resolver_register_rule( + ATTRIBUTE(USER_CHECKSUM), + NULL, + &zwave_command_class_user_credential_user_checksum_get); + + attribute_resolver_register_rule( + ATTRIBUTE(CREDENTIAL_CHECKSUM), + NULL, + &zwave_command_class_user_credential_credential_checksum_get); + + attribute_resolver_register_rule( + ATTRIBUTE(ADMIN_PIN_CODE), + &zwave_command_class_user_credential_admin_pin_code_set, + &zwave_command_class_user_credential_admin_pin_code_get); + + // https://github.com/Z-Wave-Alliance/AWG/pull/124#discussion_r1484473752 + // Discussion about delaying the user interview process after the inclusion + + // Proposed Unify-way to delay users get AFTER interview process + attribute_store_register_callback_by_type( + &zwave_network_status_changed, + DOTDOT_ATTRIBUTE_ID_STATE_NETWORK_STATUS); + + zwave_command_handler_t handler = {}; + handler.support_handler = NULL; + handler.control_handler = zwave_command_class_user_credential_control_handler; + // CHECKME : Is this right ? + handler.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_SECURITY_2_ACCESS; + handler.manual_security_validation = false; + handler.command_class = COMMAND_CLASS_USER_CREDENTIAL; + handler.version = 1; + handler.command_class_name = "User Credential"; + handler.comments = "Experimental"; + + return zwave_command_handler_register_handler(handler); +} \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.h b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.h new file mode 100644 index 0000000000..72ae89c33c --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +/** + * @defgroup zwave_command_class_user_credential + * @brief Sound Switch Command Class handlers and control function + * + * This module implement some of the functions to control the + * Sound Switch Command Class + * + * @{ + */ + +#ifndef ZWAVE_COMMAND_CLASS_USER_CREDENTIAL_H +#define ZWAVE_COMMAND_CLASS_USER_CREDENTIAL_H + +#include "sl_status.h" +#include "zwave_command_class_user_credential_types.h" +#include "attribute_store.h" + +#ifdef __cplusplus +#include +#include "sl_log.h" +extern "C" { +#endif + + +typedef void (*user_credential_slot_changed_callback_t)( + const user_credential_credential_identifier_t old_credential_slot_id, + const attribute_store_node_t new_credential_node); + +void zwave_command_class_user_credential_set_uuic_slot_changed_callback( + user_credential_slot_changed_callback_t callback); + + +sl_status_t zwave_command_class_user_credential_init(); + +#ifdef __cplusplus +} // extern "C" +typedef void (*user_credential_slot_message_callback_t)( + sl_log_level level, const std::string& message); +void zwave_command_class_user_credential_set_message_callback( + user_credential_slot_message_callback_t callback); +#endif + + + + +#endif //ZWAVE_COMMAND_CLASS_USER_CREDENTIAL_H + /** @} end zwave_command_class_user_credential */ \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential_api.cpp b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential_api.cpp new file mode 100644 index 0000000000..f1c45093d3 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential_api.cpp @@ -0,0 +1,906 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#include "zwave_command_class_user_credential_api.h" + +#include "zap-types.h" + +// Private definitions +#include "private/user_credential/user_credential_helpers.hpp" +#include "private/user_credential/user_credential_user_capabilities.h" +#include "private/user_credential/user_credential_credential_capabilities.h" +#include "private/user_credential/user_credential_credential_type_capabilities.h" + +// Cpp includes +#include +#include + +using namespace user_credential_helpers; + +/** + * @brief Setup user attributes (desired values) + * + * This function sets the desired values of the user attributes in the attribute store. + * If attributes are not present, they are created. + */ +void setup_user(attribute_store::attribute user_id_node, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + user_credential_user_active_state_t user_active_state, + user_credential_expiring_timeout_minutes_t expiring_timeout, + user_credential_user_name_encoding_t user_name_encoding, + std::string user_name) +{ + user_id_node.emplace_node(ATTRIBUTE(USER_TYPE)).set_desired(user_type); + user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_RULE)) + .set_desired(credential_rule); + user_id_node.emplace_node(ATTRIBUTE(USER_ACTIVE_STATE)) + .set_desired(user_active_state); + user_id_node.emplace_node(ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES)) + .set_desired(expiring_timeout); + user_id_node.emplace_node(ATTRIBUTE(USER_NAME_ENCODING)) + .set_desired(user_name_encoding); + user_id_node.emplace_node(ATTRIBUTE(USER_NAME)).set_desired(user_name); +} + +sl_status_t zwave_command_class_user_credential_add_new_user( + attribute_store_node_t node, + user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + user_credential_user_active_state_t user_active_state, + user_credential_expiring_timeout_minutes_t expiring_timeout, + user_credential_user_name_encoding_t user_name_encoding, + const char *user_name) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_add_new_user called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + sl_log_debug(LOG_TAG, "\tuser_type : %d", user_type); + sl_log_debug(LOG_TAG, "\tcredential_rule : %d", credential_rule); + sl_log_debug(LOG_TAG, "\tuser_active_state : %d", user_active_state); + sl_log_debug(LOG_TAG, "\texpiring_timeout : %d", expiring_timeout); + sl_log_debug(LOG_TAG, "\tuser_name_encoding : %d", user_name_encoding); + sl_log_debug(LOG_TAG, "\tuser_name : %s", user_name); + + auto endpoint_node = attribute_store::attribute(node); + + // Check user id + if (user_id == 0) { + sl_log_error(LOG_TAG, "User ID 0 is reserved. Not adding user."); + return SL_STATUS_FAIL; + } + + // Node already exists, can't create user. + if (user_exists(endpoint_node, user_id)) { + sl_log_error(LOG_TAG, + "User with ID %d already exists. Not adding user.", + user_id); + return SL_STATUS_FAIL; + } + + try { + // Check capabilites + auto capabilites = user_credential::user_capabilities(endpoint_node); + if (!capabilites.is_user_valid(user_id, + user_type, + credential_rule, + user_name)) { + sl_log_error(LOG_TAG, + "User capabilities are not valid. Not adding user."); + return SL_STATUS_FAIL; + } + + if (user_type != USER_CREDENTIAL_USER_TYPE_EXPIRING_USER) { + if (expiring_timeout != 0) { + sl_log_warning( + LOG_TAG, + "Expiring timeout set for non-expiring user, set value to 0."); + } + expiring_timeout = 0; + } + + // Create the user node + auto user_id_node = endpoint_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + DESIRED_ATTRIBUTE); + // Create user attributes + setup_user(user_id_node, + user_type, + credential_rule, + user_active_state, + expiring_timeout, + user_name_encoding, + user_name); + + // Finally set operation type add + set_user_operation_type(user_id_node, USER_CREDENTIAL_OPERATION_TYPE_ADD); + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, "Error while adding user : %s", e.what()); + return SL_STATUS_FAIL; + } + sl_log_debug(LOG_TAG, "Add user with ID %d", user_id); + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_delete_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_delete_user called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + + try { + if (!user_exists(endpoint_node, user_id)) { + sl_log_error(LOG_TAG, + "User with ID %d doesn't exists. Not deleting user.", + user_id); + return SL_STATUS_FAIL; + } + + attribute_store_node_t user_id_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + + // Finally set operation type delete + set_user_operation_type(user_id_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, "Error while deleting user : %s", e.what()); + return SL_STATUS_FAIL; + } + sl_log_debug(LOG_TAG, "Remove user with ID %d", user_id); + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_modify_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + user_credential_user_active_state_t user_active_state, + user_credential_expiring_timeout_minutes_t expiring_timeout, + user_credential_user_name_encoding_t user_name_encoding, + const char *user_name) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_modify_user called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + sl_log_debug(LOG_TAG, "\tuser_type : %d", user_type); + sl_log_debug(LOG_TAG, "\tcredential_rule : %d", credential_rule); + sl_log_debug(LOG_TAG, "\tuser_active_state : %d", user_active_state); + sl_log_debug(LOG_TAG, "\texpiring_timeout : %d", expiring_timeout); + sl_log_debug(LOG_TAG, "\tuser_name_encoding : %d", user_name_encoding); + sl_log_debug(LOG_TAG, "\tuser_name : %s", user_name); + + try { + // Check user id + if (user_id == 0) { + sl_log_error(LOG_TAG, "User ID 0 is reserved. Can't modify user."); + return SL_STATUS_FAIL; + } + + if (!user_exists(endpoint_node, user_id)) { + sl_log_error(LOG_TAG, + "User with ID %d doesn't exists. Can't modify user.", + user_id); + return SL_STATUS_FAIL; + } + + // Check if the user already exists + attribute_store_node_t user_id_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + + // Check capabilites + auto capabilites = user_credential::user_capabilities(endpoint_node); + if (!capabilites.is_user_valid(user_id, + user_type, + credential_rule, + user_name)) { + sl_log_error(LOG_TAG, + "User capabilities are not valid. Not adding user."); + return SL_STATUS_FAIL; + } + + // Modify user attributes + setup_user(user_id_node, + user_type, + credential_rule, + user_active_state, + expiring_timeout, + user_name_encoding, + user_name); + + set_user_operation_type(user_id_node, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); + sl_log_debug(LOG_TAG, "Modify user with ID %d", user_id); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while modifying user %d : %s", + user_id, + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_add_new_credential( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const char *credential_data) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_add_new_credential called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + sl_log_debug(LOG_TAG, "\tcredential_type : %d", credential_type); + sl_log_debug(LOG_TAG, "\tcredential_slot : %d", credential_slot); + sl_log_debug(LOG_TAG, "\tcredential_data : %s", credential_data); + + try { + // Check if parameters are ok + if (credential_type == 0 || credential_slot == 0) { + sl_log_error( + LOG_TAG, + "Credential Type and Slot 0 are reserved. Not adding credentials."); + return SL_STATUS_FAIL; + } + + auto capabilities + = user_credential::credential_type_capabilities(endpoint_node, + credential_type); + + if (!capabilities.is_slot_valid(credential_slot)) { + sl_log_error(LOG_TAG, + "Credential slot %d for Credential Type %d is not valid. " + "Not adding credentials.", + credential_slot, + credential_type); + return SL_STATUS_FAIL; + } + + if (!is_credential_available(endpoint_node, + credential_type, + credential_slot)) { + sl_log_error(LOG_TAG, + "Credential slot %d for Credential Type %d already exists." + "Not adding credentials.", + credential_slot, + credential_type); + return SL_STATUS_FAIL; + } + + auto user_id_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + // Get or create credential type node + auto credential_type_node + = user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), credential_type); + + // Process credential data + std::vector credential_data_vector + = capabilities.convert_and_validate_credential_data(credential_data, + credential_slot); + + auto credential_slot_node + = credential_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + DESIRED_ATTRIBUTE); + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA), + credential_data_vector, + DESIRED_ATTRIBUTE); + set_credential_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_ADD); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while trying to add a new credential : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_modify_credential( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const char *credential_data) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_modify_credential called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + sl_log_debug(LOG_TAG, "\tcredential_type : %d", credential_type); + sl_log_debug(LOG_TAG, "\tcredential_slot : %d", credential_slot); + sl_log_debug(LOG_TAG, "\tcredential_data : %s", credential_data); + + // Check if parameters are ok + if (user_id == 0 || credential_type == 0 || credential_slot == 0) { + sl_log_error(LOG_TAG, + "User ID, Credential Type and Slot 0 are reserved. Not " + "modifying credentials."); + return SL_STATUS_FAIL; + } + + try { + auto nodes + = get_credential_identifier_nodes(endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, REPORTED_ATTRIBUTE}, + {credential_slot, REPORTED_ATTRIBUTE}); + // Get current credential slot node + auto credential_slot_node = nodes.slot_node; + // Process credential data + auto capabilities + = user_credential::credential_type_capabilities(endpoint_node, + credential_type); + std::vector credential_data_vector + = capabilities.convert_and_validate_credential_data(credential_data, + credential_slot); + // Modify current data + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA)) + .set_desired(credential_data_vector); + + // Finally set operation type modify + set_credential_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while trying to modify a credential : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_delete_credential( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot) +{ + sl_log_debug(LOG_TAG, + "Delete credential slot %d (credential type %d, user id %d)", + credential_slot, + credential_type, + user_id); + + try { + auto nodes + = get_credential_identifier_nodes(endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, REPORTED_ATTRIBUTE}, + {credential_slot, REPORTED_ATTRIBUTE}); + + // Finally set operation type delete + set_credential_operation_type(nodes.slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while trying to delete a credential : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_delete_all_users( + attribute_store_node_t endpoint_node) +{ + attribute_store::attribute cpp_endpoint_node(endpoint_node); + user_credential_user_unique_id_t user_id = 0; + auto user_id_node + = cpp_endpoint_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Finally set operation type delete + set_user_operation_type(user_id_node, USER_CREDENTIAL_OPERATION_TYPE_DELETE); + + sl_log_debug(LOG_TAG, + "Delete all user operation received. Creating user with id %d " + "to send a User SET.", + user_id); + return SL_STATUS_OK; +} + +void trigger_credential_deletion(attribute_store::attribute endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot) +{ + auto credential_slot_node + = endpoint_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id) + .emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), credential_type) + .emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), credential_slot); + + // Finally set operation type delete + set_credential_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_DELETE); + + sl_log_debug(LOG_TAG, + "Creating user with id %d, credential type %d and slot " + "both to %d to send a Credential SET.", + user_id, + credential_type, + credential_slot); +} + +sl_status_t zwave_command_class_user_credential_delete_all_credentials( + attribute_store_node_t endpoint_node) +{ + sl_log_debug(LOG_TAG, "Delete all credential operation received"); + + trigger_credential_deletion(endpoint_node, 0, 0, 0); + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_delete_all_credentials_by_type( + attribute_store_node_t endpoint_node, user_credential_type_t credential_type) +{ + sl_log_debug(LOG_TAG, + "Delete all credential of type %d operation received", + credential_type); + + trigger_credential_deletion(endpoint_node, 0, credential_type, 0); + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_delete_all_credentials_for_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id) +{ + sl_log_debug(LOG_TAG, + "Delete all credential for user %d operation received", + user_id); + + trigger_credential_deletion(endpoint_node, user_id, 0, 0); + + return SL_STATUS_OK; +} + +sl_status_t + zwave_command_class_user_credential_delete_all_credentials_for_user_by_type( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type) +{ + sl_log_debug(LOG_TAG, + "Delete all credential for user %d and credential type %d " + "operation received", + user_id, + credential_type); + + trigger_credential_deletion(endpoint_node, user_id, credential_type, 0); + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_credential_learn_start_add( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + user_credential_learn_timeout_t credential_learn_timeout) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_credential_learn_start (Add)" + " called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + sl_log_debug(LOG_TAG, "\tcredential_type : %d", credential_type); + sl_log_debug(LOG_TAG, "\tcredential_slot : %d", credential_slot); + sl_log_debug(LOG_TAG, + "\tcredential_learn_timeout : %d", + credential_learn_timeout); + + auto credential_type_capabilities + = user_credential::credential_type_capabilities(endpoint_node, + credential_type); + + if (!credential_type_capabilities.is_learn_supported()) { + sl_log_error(LOG_TAG, + "Learn is not supported for credential type %d. Not starting " + "learn process.", + credential_type); + return SL_STATUS_FAIL; + } + + if (!credential_type_capabilities.is_slot_valid(credential_slot)) { + sl_log_error(LOG_TAG, + "Credential slot %d is not valid for Credential Type %d. Not " + "starting learn process.", + credential_slot, + credential_type); + return SL_STATUS_FAIL; + } + + // Check parameters values + if (credential_type == 0 || credential_slot == 0) { + sl_log_error( + LOG_TAG, + "Credential Type and Slot 0 are reserved. Not adding credentials."); + return SL_STATUS_FAIL; + } + + if (!is_credential_available(endpoint_node, + credential_type, + credential_slot)) { + sl_log_error(LOG_TAG, + "Credential slot %d for Credential Type %d already exists." + "Not adding credentials.", + credential_slot, + credential_type); + return SL_STATUS_FAIL; + } + + try { + auto user_id_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + auto credential_type_node + = user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), credential_type); + + // Create credential slot with reported value since we don't want + // to trigger a Credential Get right away + auto credential_slot_node + = credential_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot); + + if (credential_learn_timeout == 0) { + credential_learn_timeout + = credential_type_capabilities.get_learn_recommended_timeout(); + sl_log_debug(LOG_TAG, + "Credential learn timeout is 0. Setting it to default " + "reported value (%d seconds).", + credential_learn_timeout); + } + + // Set attributes for Credential Learn + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_LEARN_TIMEOUT)) + .set_reported(credential_learn_timeout); + + set_credential_learn_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_ADD); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, "Error in credential learn start : %s", e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_credential_learn_start_modify( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + user_credential_learn_timeout_t credential_learn_timeout) +{ + // Debug info + sl_log_debug( + LOG_TAG, + "zwave_command_class_user_credential_credential_learn_start (modify) " + "called with : "); + sl_log_debug(LOG_TAG, "\tuser_id : %d", user_id); + sl_log_debug(LOG_TAG, "\tcredential_type : %d", credential_type); + sl_log_debug(LOG_TAG, "\tcredential_slot : %d", credential_slot); + sl_log_debug(LOG_TAG, + "\tcredential_learn_timeout : %d", + credential_learn_timeout); + + auto credential_type_capabilities + = user_credential::credential_type_capabilities(endpoint_node, + credential_type); + + if (!credential_type_capabilities.is_learn_supported()) { + sl_log_error(LOG_TAG, + "Learn is not supported for credential type %d. Not starting " + "learn process.", + credential_type); + return SL_STATUS_FAIL; + } + + // Check parameters values + if (credential_type == 0 || credential_slot == 0) { + sl_log_error( + LOG_TAG, + "Credential Type and Slot 0 are reserved. Not adding credentials."); + return SL_STATUS_FAIL; + } + + if (credential_learn_timeout == 0) { + credential_learn_timeout + = credential_type_capabilities.get_learn_recommended_timeout(); + sl_log_debug(LOG_TAG, + "Credential learn timeout is 0. Setting it to default " + "reported value (%d seconds).", + credential_learn_timeout); + } + + try { + auto nodes + = get_credential_identifier_nodes(endpoint_node, + {user_id, REPORTED_ATTRIBUTE}, + {credential_type, REPORTED_ATTRIBUTE}, + {credential_slot, REPORTED_ATTRIBUTE}); + + auto credential_slot_node = nodes.slot_node; + + // Set attributes for Credential Learn + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_LEARN_TIMEOUT)) + .set_reported(credential_learn_timeout); + set_credential_learn_operation_type(credential_slot_node, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error in credential learn start modify : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_credential_learn_stop( + attribute_store_node_t endpoint_node) +{ + uint8_t stop_flag = 1; + + return attribute_store_set_child_desired(endpoint_node, + ATTRIBUTE(CREDENTIAL_LEARN_STOP), + &stop_flag, + sizeof(stop_flag)); +} + +sl_status_t zwave_command_class_user_credential_uuic_association_set( + attribute_store_node_t endpoint_node, + user_credential_type_t credential_type, + user_credential_user_unique_id_t source_user_id, + user_credential_slot_t source_credential_slot, + user_credential_user_unique_id_t destination_user_id, + user_credential_slot_t destination_credential_slot) +{ + try { + auto nodes = get_credential_identifier_nodes( + endpoint_node, + {source_user_id, REPORTED_ATTRIBUTE}, + {credential_type, REPORTED_ATTRIBUTE}, + {source_credential_slot, REPORTED_ATTRIBUTE}); + + nodes.slot_node.emplace_node(ATTRIBUTE(ASSOCIATION_DESTINATION_USER_ID)) + .set_desired(destination_user_id); + + // Slot ID last since it's this attribute that is bound to the SET command + nodes.slot_node + .emplace_node(ATTRIBUTE(ASSOCIATION_DESTINATION_CREDENTIAL_SLOT)) + .set_desired(destination_credential_slot); + } catch (std::exception &e) { + sl_log_error(LOG_TAG, + "Error while setting up uuic asociation set : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_get_user_checksum( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id) +{ + try { + auto user_id_node + = get_user_unique_id_node(endpoint_node, user_id, REPORTED_ATTRIBUTE); + + auto checksum_node = user_id_node.emplace_node(ATTRIBUTE(USER_CHECKSUM)); + // If node already exists, we clear its value to trigger the GET + checksum_node.clear_reported(); + checksum_node.clear_desired(); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while setting up user get checksum : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_get_credential_checksum( + attribute_store_node_t endpoint_node, user_credential_type_t credential_type) +{ + try { + attribute_store::attribute cpp_endpoint_node(endpoint_node); + auto supported_credential_type_node + = cpp_endpoint_node.child_by_type_and_value( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + credential_type); + + if (!supported_credential_type_node.is_valid()) { + sl_log_error(LOG_TAG, + "Can't find supported credential type %d. Not setting up " + "Checksum get.", + credential_type); + return SL_STATUS_FAIL; + } + + auto checksum_node = supported_credential_type_node.emplace_node( + ATTRIBUTE(CREDENTIAL_CHECKSUM)); + // If node already exists, we clear its value to trigger the GET + checksum_node.clear_reported(); + checksum_node.clear_desired(); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while setting up credential get checksum : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_get_all_users_checksum( + attribute_store_node_t endpoint_node) +{ + try { + attribute_store::attribute cpp_endpoint_node(endpoint_node); + auto checksum_node + = cpp_endpoint_node.emplace_node(ATTRIBUTE(ALL_USERS_CHECKSUM)); + checksum_node.clear_reported(); + checksum_node.clear_desired(); + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while setting up get all users checksum : %s", + e.what()); + return SL_STATUS_FAIL; + } + + return SL_STATUS_OK; +} + +sl_status_t zwave_command_class_user_credential_set_admin_pin_code( + attribute_store_node_t endpoint_node, const char *raw_credential_data) +{ + try { + // Capabilities + user_credential::credential_type_capabilities credential_type_capabilities( + endpoint_node, + ZCL_CRED_TYPE_PIN_CODE); + user_credential::credential_capabilities credential_capabilities( + endpoint_node); + + // Base check + if (!credential_capabilities.is_admin_code_supported()) { + sl_log_error( + LOG_TAG, + "Admin PIN code not supported."); + return SL_STATUS_FAIL; + } + + // Get credential data in the right format + auto credential_data + = credential_type_capabilities.convert_credential_data(raw_credential_data); + + // Create or get admin pin code node + auto admin_pin_code_node = attribute_store::attribute(endpoint_node) + .emplace_node(ATTRIBUTE(ADMIN_PIN_CODE)); + + // Check if we can deactivate it + if (credential_data.empty() + && !credential_capabilities.is_admin_code_deactivation_supported()) { + sl_log_error( + LOG_TAG, + "Admin PIN code deactivation disabled, can't deactivate it."); + return SL_STATUS_FAIL; + } + + // Special case if credential data is empty + // Need this since no value is the same as undefined for the attribute store + if (credential_data.empty()) { + sl_log_debug(LOG_TAG, "Admin pin code data is empty. Deactivating it."); + set_empty_admin_code(admin_pin_code_node, DESIRED_ATTRIBUTE); + } else if (credential_type_capabilities.is_credential_data_valid( + credential_data)) { + // Set new value for desired node + admin_pin_code_node.set_desired(credential_data); + } else { + sl_log_error(LOG_TAG, + "Admin pin code data is not valid. Not setting it."); + return SL_STATUS_FAIL; + } + + } catch (const std::exception &e) { + sl_log_error(LOG_TAG, + "Error while setting up set admin pin code : %s", + e.what()); + return SL_STATUS_FAIL; + } + return SL_STATUS_OK; +} + +bool zwave_command_class_user_credential_supports( + attribute_store_node_t endpoint_node, uint8_t command_id) +{ + // Checks first if the node supports User Credential + auto cpp_endpoint_node = attribute_store::attribute(endpoint_node); + if (!cpp_endpoint_node.child_by_type(ATTRIBUTE(VERSION)).is_valid()) { + return false; + } + + // Commands that don't need specific capabilities + // Note : We don't have the granularity to check if the learn is supported for a specific credential at this level + // so some commands (e.g CREDENTIAL_LEARN_START) are marked as supported even if the credential type doesn't support it. + // The API call will check that for us instead. + const std::vector supported_commands = { + USER_SET, + CREDENTIAL_SET, + CREDENTIAL_LEARN_START, + CREDENTIAL_LEARN_CANCEL, + USER_CREDENTIAL_ASSOCIATION_SET + }; + + // Check if we support the command_id without checking the capabilities + if (std::find(supported_commands.begin(), + supported_commands.end(), + command_id) + != supported_commands.end()) { + return true; + } + + user_credential::user_capabilities user_capabilities(endpoint_node); + user_credential::credential_capabilities credential_capabilities( + endpoint_node); + + switch (command_id) { + case ALL_USERS_CHECKSUM_GET: + return user_capabilities.is_all_users_checksum_supported(); + case USER_CHECKSUM_GET: + return user_capabilities.is_user_checksum_supported(); + case CREDENTIAL_CHECKSUM_GET: + return credential_capabilities.is_credential_checksum_supported(); + case ADMIN_PIN_CODE_SET: + return credential_capabilities.is_admin_code_supported(); + default: + sl_log_critical( + LOG_TAG, + "Unknown command %d in zwave_command_class_user_credential_supports", + command_id); + return false; + } +} + +bool zwave_command_class_user_credential_supports_admin_pin_code_deactivation( + attribute_store_node_t endpoint_node) +{ + user_credential::credential_capabilities credential_capabilities( + endpoint_node); + return credential_capabilities.is_admin_code_deactivation_supported(); +} diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential_api.h b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential_api.h new file mode 100644 index 0000000000..83e662fa20 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_class_user_credential_api.h @@ -0,0 +1,403 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +/** + * @defgroup zwave_command_class_user_credential_api + * @brief User Credential Command Class High Level API + * + * @see zwave_command_class_user_credential for interaction with zwave frames and end device + * + */ + +#ifndef ZWAVE_COMMAND_CLASS_USER_CREDENTIAL_API_H +#define ZWAVE_COMMAND_CLASS_USER_CREDENTIAL_API_H + +#include "sl_status.h" +#include "zwave_command_class_user_credential_types.h" +#include "attribute_store.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Send a new user command (User SET) to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should NOT exists and NOT be 0 + * @param user_type The type of the user credential. + * @param credential_rule The rule associated with the user credential. + * @param user_active_state The active state of the user. + * @param expiring_timeout The timeout for the user credential to expire, in minutes. Will be ignored unless user_type == 0x07. + * @param user_name_encoding The encoding format of the user name. + * @param user_name The name of the user. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id already exists or is 0. + */ +sl_status_t zwave_command_class_user_credential_add_new_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + user_credential_user_active_state_t user_active_state, + user_credential_expiring_timeout_minutes_t expiring_timeout, + user_credential_user_name_encoding_t user_name_encoding, + const char *user_name); + + +/** + * @brief Send a modify user command (User SET) to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Should NOT be 0. + * @param user_type The type of the user credential. + * @param credential_rule The rule associated with the user credential. + * @param user_active_state The active state of the user. + * @param expiring_timeout The timeout for the user credential to expire, in minutes. Will be ignored unless user_type == 0x07. + * @param user_name_encoding The encoding format of the user name. + * @param user_name The name of the user. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id doesn't exists or is 0. + */ +sl_status_t zwave_command_class_user_credential_modify_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t user_type, + user_credential_rule_t credential_rule, + user_credential_user_active_state_t user_active_state, + user_credential_expiring_timeout_minutes_t expiring_timeout, + user_credential_user_name_encoding_t user_name_encoding, + const char *user_name); + +/** + * @brief Send a delete user command (User SET) to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id doesn't exists. +*/ +sl_status_t zwave_command_class_user_credential_delete_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id); + +/** + * @brief Send a new credential command (Credential SET) to the end device + * + * The credential data expected is an UTF-8 string. Some check/conversion will be performed based on the credential type. + * - PINCode : Refuse any values that is not between '0' and '9'. + * - Password : Will be stored in UTF-16 format. The exposed value still be in UTF-8, but the end device will receive UTF-16 data. + * - Others : Will be stored as is. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * @param credential_type The type of the credential. Can exist or not. Cannot be 0. + * @param credential_slot The slot of the credential. Should not exists. Cannot be 0. + * @param credential_data Raw data of the credential. Checks are performed based on the credential type. + * + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id doesn't exists or the credential_slot already exists or one of the value is 0. Also if the credential data is invalid. + */ +sl_status_t zwave_command_class_user_credential_add_new_credential( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const char* credential_data); + +/** + * @brief Send a modify credential command (Credential SET) to the end device + * + * The credential data expected is an UTF-8 string. Some check/conversion will be performed based on the credential type. + * - PINCode : Refuse any values that is not between '0' and '9'. + * - Password : Will be stored in UTF-16 format. The exposed value still be in UTF-8, but the end device will receive UTF-16 data. + * - Others : Will be stored as is. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * @param credential_type The type of the credential. Should exists. Cannot be 0. + * @param credential_slot The slot of the credential. Should exists. Cannot be 0. + * @param credential_data Raw data of the credential. Checks are performed based on the credential type. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id, credential type or credential slot doesn't exists or one of the value is 0. Also if the credential data is invalid. + */ +sl_status_t zwave_command_class_user_credential_modify_credential( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + const char* credential_data +); + +/** + * @brief Send a delete credential command (Credential SET) to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * @param credential_type The type of the credential. Should exists. Cannot be 0. + * @param credential_slot The slot of the credential. Should exists. Cannot be 0. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id, credential type or credential slot doesn't exists or one of the value is 0. +*/ +sl_status_t zwave_command_class_user_credential_delete_credential( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot); + +/** + * @brief Send a delete all users command (User SET) to the end device + * + * It will send an User SET command with user id = 0 and operation type delete to remove all users. + * (CC:0083.01.05.11.009) + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise +*/ +sl_status_t zwave_command_class_user_credential_delete_all_users( + attribute_store_node_t endpoint_node); + +/** + * @brief Send a delete all credentials command (Credential SET) to the end device + * + * It will send an Credential SET command with user_id, credential_type and credential_slot = 0 and operation type delete to remove all credentials. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise +*/ +sl_status_t zwave_command_class_user_credential_delete_all_credentials( + attribute_store_node_t endpoint_node); + +/** + * @brief Send a delete all credentials by type command (Credential SET) to the end device + * + * It will send an Credential SET command with user_id = 0 and operation type delete to remove all credentials of the specified type. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param credential_type The type of the credential. Should exists. Cannot be 0. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise +*/ +sl_status_t + zwave_command_class_user_credential_delete_all_credentials_by_type( + attribute_store_node_t endpoint_node, + user_credential_type_t credential_type); + +/** + * @brief Send a delete all credentials for user command (Credential SET) to the end device + * + * It will send an Credential SET command with credential_type and credential_slot = 0 and operation type delete to remove all credentials of the specified user. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise + * + * @note This function will not remove the user itself. + */ +sl_status_t zwave_command_class_user_credential_delete_all_credentials_for_user( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id); + +/** + * @brief Send a delete all credentials for user by type command (Credential SET) to the end device + * + * It will send an Credential SET command with credential_slot = 0 and operation type delete to remove all credentials of the specified user and type. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * @param credential_type The type of the credential. Should exists. Cannot be 0. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise + * + * @note This function will not remove the user itself. +*/ +sl_status_t + zwave_command_class_user_credential_delete_all_credentials_for_user_by_type( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type); + + +/** + * @brief Send new credential command (Credential Learn Start) with operation type Add to the end device + * + * @note The credential type must be supporting the Credential Learn feature. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * @param credential_type The type of the credential. Can exist or not. Cannot be 0. + * @param credential_slot The slot of the credential. Should not exists. Cannot be 0. + * @param credential_learn_timeout Timeout for each credential learn step on the node, in seconds. Can be set to 0 to use recommended timeout by the end device. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id doesn't exists or the credential_slot already exists or one of the value is 0. Also if the credential type doesn't support the learn mode. + */ +sl_status_t zwave_command_class_user_credential_credential_learn_start_add( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + user_credential_learn_timeout_t credential_learn_timeout); + +/** + * @brief Send new credential command (Credential Learn Start) with operation type Modify to the end device + * + * @note The credential type must be supporting the Credential Learn feature. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the user. Should exists. Cannot be 0. + * @param credential_type The type of the credential. Should exists. Cannot be 0. + * @param credential_slot The slot of the credential. Should exists. Cannot be 0. + * @param credential_learn_timeout Timeout for each credential learn step on the node, in seconds. Can be set to 0 to use recommended timeout by the end device. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id doesn't exists or the credential_slot/credential type is 0 or does not exists. Also if the credential type doesn't support the learn mode. + */ +sl_status_t zwave_command_class_user_credential_credential_learn_start_modify( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + user_credential_learn_timeout_t credential_learn_timeout); + +/** + * @brief Send new credential command (Credential Learn Stop) to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise +*/ +sl_status_t zwave_command_class_user_credential_credential_learn_stop( + attribute_store_node_t endpoint_node); + + +/** + * @brief Send a User Unique Identifier Credential Association Set to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param credential_type The type of the credential. + * @param source_user_id The unique ID of the source user. Should exists. Cannot be 0. + * @param source_credential_slot The slot of the source credential. Should exists. Cannot be 0. + * @param destination_user_id The unique ID of the destination user. Cannot be 0. + * @param destination_credential_slot The slot of the destination credential. Should not exists. Cannot be 0. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id already exists or is 0. + */ +sl_status_t zwave_command_class_user_credential_uuic_association_set( + attribute_store_node_t endpoint_node, + user_credential_type_t credential_type, + user_credential_user_unique_id_t source_user_id, + user_credential_slot_t source_credential_slot, + user_credential_user_unique_id_t destination_user_id, + user_credential_slot_t destination_credential_slot); + +/** + * @brief Send a User Checksum Get command to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param user_id The unique ID of the source user. Should exists. Cannot be 0. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the user_id doesn't exists or is 0. + */ +sl_status_t zwave_command_class_user_credential_get_user_checksum( + attribute_store_node_t endpoint_node, + user_credential_user_unique_id_t user_id); + + +/** + * @brief Send a Credential Checksum Get command to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param credential_type The type of the credential. Cannot be 0 + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the credential_type is not supported or is 0. + */ +sl_status_t zwave_command_class_user_credential_get_credential_checksum( + attribute_store_node_t endpoint_node, + user_credential_type_t credential_type); + + +/** + * @brief Send a All Users Checksum Get command to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL otherwise + */ +sl_status_t zwave_command_class_user_credential_get_all_users_checksum( + attribute_store_node_t endpoint_node); + +/** + * @brief Send a Set Admin Pin Code command to the end device + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param credential_data The new admin pin code. Must contains only digits. + * + * @return sl_status_t SL_STATUS_OK if the attribute store was updated successfully + * @return sl_status_t SL_STATUS_FAIL if the credential_data is invalid. + */ +sl_status_t zwave_command_class_user_credential_set_admin_pin_code( + attribute_store_node_t endpoint_node, + const char* credential_data); + +/** + * @brief Return true if the User Credential Command Class supports the Admin Pin Code Deactivation command + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * + * @return true if the command is supported + * @return false if the command is not supported + */ +bool zwave_command_class_user_credential_supports_admin_pin_code_deactivation( + attribute_store_node_t endpoint_node); + +/** + * @brief Test if given command id is supported by the User Credential Command Class + * + * It will perform a check first to see if given node is supporting the User Credential Command Class. + * If not it will return false. + * + * @param endpoint_node The attribute store node of the endpoint where the user credential is located. + * @param command_id The command id to test + * + * @return true if the command is supported + * @return false if the command is not supported + */ +bool zwave_command_class_user_credential_supports( + attribute_store_node_t endpoint_node, uint8_t command_id); + +#ifdef __cplusplus +} +#endif + +#endif //ZWAVE_COMMAND_CLASS_USER_CREDENTIAL_API_H + /** @} end zwave_command_class_user_credential */ \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c index a4c8f32b62..d6f457e71a 100644 --- a/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_fixt.c @@ -57,6 +57,7 @@ #include "zwave_command_class_indicator_control.h" #include "zwave_command_class_manufacturer_specific_control.h" #include "zwave_command_class_humidity_control_mode.h" +#include "zwave_command_class_user_credential.h" // Generic includes #include @@ -121,6 +122,7 @@ sl_status_t zwave_command_classes_init() status |= zwave_command_class_time_init(); status |= zwave_command_class_transport_service_init(); status |= zwave_command_class_user_code_init(); + status |= zwave_command_class_user_credential_init(); status |= zwave_command_class_version_init(); status |= zwave_command_class_wake_up_init(); status |= zwave_command_class_zwave_plus_info_init(); diff --git a/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_utils.c b/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_utils.c index d927408446..18db01916e 100644 --- a/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_utils.c +++ b/applications/zpc/components/zwave_command_classes/src/zwave_command_classes_utils.c @@ -73,8 +73,14 @@ zwave_cc_version_t zwave_command_class_get_version_from_node(attribute_store_node_t node, zwave_command_class_t command_class) { - attribute_store_node_t endpoint_node - = attribute_store_get_first_parent_with_type(node, ATTRIBUTE_ENDPOINT_ID); + attribute_store_node_t endpoint_node; + + if (attribute_store_get_node_type(node) == ATTRIBUTE_ENDPOINT_ID) { + endpoint_node = node; + } else { + endpoint_node + = attribute_store_get_first_parent_with_type(node, ATTRIBUTE_ENDPOINT_ID); + } attribute_store_node_t version_node = attribute_store_get_first_child_by_type( endpoint_node, diff --git a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt index 0739c357c2..4cc298e0b5 100644 --- a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt +++ b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt @@ -4,6 +4,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") add_link_options("-Wl,--unresolved-symbols=ignore-in-object-files" "-Wl,--allow-multiple-definition") endif() + +add_subdirectory(helpers) + set(MOCK_LIBS uic_attribute_store_mock zpc_attribute_store_mock @@ -21,9 +24,8 @@ set(MOCK_LIBS add_library(zwave_command_classes_test $) target_link_libraries(zwave_command_classes_test PUBLIC zwave_command_classes) -add_library(zwave_command_class_test_helper zwave_command_class_test_helper.c) target_link_libraries( - zwave_command_class_test_helper + zwave_command_class_test_helpers zwave_command_classes unity2 zwave_tx_scheme_selector_mock @@ -41,7 +43,7 @@ target_add_unittest( SOURCES zwave_command_class_time_test.c DEPENDS - zwave_command_class_test_helper + zwave_command_class_test_helpers ${MOCK_LIBS}) target_add_unittest( @@ -51,7 +53,7 @@ target_add_unittest( SOURCES zwave_command_class_powerlevel_test.c DEPENDS - zwave_command_class_test_helper + zwave_command_class_test_helpers uic_contiki_stub ${MOCK_LIBS}) @@ -63,7 +65,7 @@ target_add_unittest( zwave_command_class_manufacturer_specific_test.c zwave_command_class_manufacturer_specific_test_zpc_config_mock.c DEPENDS - zwave_command_class_test_helper + zwave_command_class_test_helpers zwave_security_validation_mock ${MOCK_LIBS}) @@ -87,7 +89,7 @@ target_add_unittest( SOURCES zwave_command_class_indicator_test.c DEPENDS - zwave_command_class_test_helper + zwave_command_class_test_helpers uic_attribute_store_mock zwave_command_handler_mock zwave_controller_mock @@ -103,7 +105,7 @@ target_add_unittest( zwave_command_class_notification_test.c DEPENDS ${MOCK_LIBS} - zwave_command_class_test_helper) + zwave_command_class_test_helpers) target_add_unittest( zwave_command_classes @@ -212,7 +214,7 @@ target_add_unittest( SOURCES zwave_command_class_zwaveplus_info_test.c DEPENDS - zwave_command_class_test_helper + zwave_command_class_test_helpers uic_contiki_stub ${MOCK_LIBS}) @@ -832,4 +834,25 @@ target_add_unittest( zpc_attribute_resolver_mock uic_dotdot_mqtt_mock) - \ No newline at end of file + + + # User credential test + target_add_unittest( + zwave_command_classes + NAME + zwave_command_class_user_credential_test + SOURCES + zwave_command_class_user_credential_test.cpp + # Allow to use notification mock + EXCLUDE + zwave_command_class_notification.cpp + DEPENDS + zwave_command_class_test_helpers + zpc_attribute_store_test_helper + zwave_controller + zwave_command_handler_mock + uic_attribute_resolver_mock + zpc_attribute_resolver_mock + uic_dotdot_mqtt_mock + zwave_network_management_mock + zwave_command_class_notification_mock) \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt.rej b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt.rej new file mode 100644 index 0000000000..0a65aecc64 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt.rej @@ -0,0 +1,76 @@ +diff a/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/test/CMakeLists.txt (rejected hunks) +@@ -4,6 +4,9 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_link_options("-Wl,--unresolved-symbols=ignore-in-object-files" + "-Wl,--allow-multiple-definition") + endif() ++ ++add_subdirectory(helpers) ++ + set(MOCK_LIBS + uic_attribute_store_mock + zpc_attribute_store_mock +@@ -21,9 +24,8 @@ set(MOCK_LIBS + add_library(zwave_command_classes_test $) + target_link_libraries(zwave_command_classes_test PUBLIC zwave_command_classes) + +-add_library(zwave_command_class_test_helper zwave_command_class_test_helper.c) + target_link_libraries( +- zwave_command_class_test_helper ++ zwave_command_class_test_helpers + zwave_command_classes + unity2 + zwave_tx_scheme_selector_mock +@@ -41,7 +43,7 @@ target_add_unittest( + SOURCES + zwave_command_class_time_test.c + DEPENDS +- zwave_command_class_test_helper ++ zwave_command_class_test_helpers + ${MOCK_LIBS}) + + target_add_unittest( +@@ -51,7 +53,7 @@ target_add_unittest( + SOURCES + zwave_command_class_powerlevel_test.c + DEPENDS +- zwave_command_class_test_helper ++ zwave_command_class_test_helpers + uic_contiki_stub + ${MOCK_LIBS}) + +@@ -63,7 +65,7 @@ target_add_unittest( + zwave_command_class_manufacturer_specific_test.c + zwave_command_class_manufacturer_specific_test_zpc_config_mock.c + DEPENDS +- zwave_command_class_test_helper ++ zwave_command_class_test_helpers + zwave_security_validation_mock + ${MOCK_LIBS}) + +@@ -87,7 +89,7 @@ target_add_unittest( + SOURCES + zwave_command_class_indicator_test.c + DEPENDS +- zwave_command_class_test_helper ++ zwave_command_class_test_helpers + uic_attribute_store_mock + zwave_command_handler_mock + zwave_controller_mock +@@ -103,7 +105,7 @@ target_add_unittest( + zwave_command_class_notification_test.c + DEPENDS + ${MOCK_LIBS} +- zwave_command_class_test_helper) ++ zwave_command_class_test_helpers) + + target_add_unittest( + zwave_command_classes +@@ -212,7 +214,7 @@ target_add_unittest( + SOURCES + zwave_command_class_zwaveplus_info_test.c + DEPENDS +- zwave_command_class_test_helper ++ zwave_command_class_test_helpers + uic_contiki_stub + ${MOCK_LIBS}) + diff --git a/applications/zpc/components/zwave_command_classes/test/helpers/CMakeLists.txt b/applications/zpc/components/zwave_command_classes/test/helpers/CMakeLists.txt new file mode 100644 index 0000000000..0e07478505 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/helpers/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(zwave_command_class_test_helpers + zwave_command_class_test_helper.cpp + zwave_resolver_function_helper.cpp + zwave_raw_frame_test_helper.c + ) + +target_include_directories(zwave_command_class_test_helpers + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(zwave_command_class_test_helpers + # Helpers + zpc_attribute_store_test_helper + # Mock + zwave_command_handler_mock + uic_attribute_resolver_mock) \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/test/helpers/zwave_command_class_test_helper.cpp b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_command_class_test_helper.cpp new file mode 100644 index 0000000000..1581ae04e6 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_command_class_test_helper.cpp @@ -0,0 +1,341 @@ + +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +// Base class +#include "zwave_command_class_test_helper.hpp" + +// Unify +#include "zwave_command_classes_utils.h" + +// C++ includes +#ifdef __cplusplus +#include +#include // memset +#include +#endif + +extern "C" { + +// Mocks +#include "zwave_command_handler_mock.h" +#include "attribute_resolver_mock.h" + +namespace zwave_command_class_test_helper +{ + +// Buffers for frame. We use a static C array here to match the C API +uint8_t received_frame[255]; +uint16_t received_frame_size; +// ZWave current command handler +zwave_command_handler_t handler; +// Resolver function helper +zwave_resolver_function_helper resolver_function_helper; + +// Current current command class id. We use uint8_t here instead of zwave_command_class_t to be able to set it directly in the tested frames. +uint8_t current_command_class_id; +// Endpoint id node wrapper +attribute_store::attribute cpp_endpoint_id_node; +// Used for report frames +zwave_controller_connection_info_t mock_connection_info; + +// Keep a copy of handler args for testing in stub function +zwave_struct_handler_args handler_args; + +//////////////////////////////////////////////////////////////////////////////////// +// Suit setup +//////////////////////////////////////////////////////////////////////////////////// + +void zwave_setUp(const zwave_struct_handler_args &args, + const command_class_init_function &init_function, + const resolver_function_map &bindings) +{ + // Create base structure + zpc_attribute_store_test_helper_create_network(); + + // Clear received frame + memset(received_frame, 0, sizeof(received_frame)); + received_frame_size = 0; + + // Unset previous definition of handler + memset(&handler, 0, sizeof(zwave_command_handler_t)); + + // Resolver function helper + resolver_function_helper.set_resolver_functions(bindings); + attribute_resolver_register_rule_Stub(&attribute_resolver_register_rule_stub); + + // Handler registration + handler_args = args; + zwave_command_handler_register_handler_Stub( + &zwave_command_handler_register_handler_stub); + + // Save current command class + current_command_class_id = handler_args.command_class_id; + + // Create wrapper around endpoint id node + cpp_endpoint_id_node = endpoint_id_node; + + // Setup connection info + mock_connection_info = {}; + mock_connection_info.remote.node_id = node_id; + mock_connection_info.remote.endpoint_id = endpoint_id; + mock_connection_info.local.is_multicast = false; + + // Call init function + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + init_function(), + "Command class init function should have return SL_STATUS_OK"); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Stub defintions +//////////////////////////////////////////////////////////////////////////////////// +sl_status_t zwave_command_handler_register_handler_stub( + zwave_command_handler_t new_command_class_handler, int cmock_num_calls) +{ + handler = new_command_class_handler; + helper_test_handler(handler_args); + return SL_STATUS_OK; +} + +sl_status_t + attribute_resolver_register_rule_stub(attribute_store_type_t node_type, + attribute_resolver_function_t set_func, + attribute_resolver_function_t get_func, + int cmock_num_calls) +{ + return resolver_function_helper.register_resolver_functions(node_type, + set_func, + get_func); +} +//////////////////////////////////////////////////////////////////////////////////// +// Frame generation helpers +//////////////////////////////////////////////////////////////////////////////////// +void zwave_frame::add(uint8_t value) +{ + this->push_back(value); +} + +void zwave_frame::add(uint16_t value) +{ + this->push_back((value & 0xFF00) >> 8); + this->push_back(value & 0x00FF); +} + +void zwave_frame::add(uint32_t value) +{ + this->push_back((value & 0xFF000000) >> 24); + this->push_back((value & 0x00FF0000) >> 16); + this->push_back((value & 0x0000FF00) >> 8); + this->push_back(value & 0x000000FF); +} + +void zwave_frame::add(const std::string &value) +{ + this->push_back(static_cast(value.size())); + for (const auto &c: value) { + this->push_back(c); + } +} + +void zwave_frame::add(const std::vector &bytes) +{ + this->push_back(static_cast(bytes.size())); + this->insert(this->end(), bytes.cbegin(), bytes.cend()); +} + +void zwave_frame::add_bitmask(uint8_t size, uint32_t bitmask) +{ + this->push_back(size); + + for (uint8_t i = 0; i < size; i++) { + uint8_t current_offset = i; + uint8_t current_shift = 8 * current_offset; + uint32_t current_bitmask = 0xFF << current_shift; + + uint8_t value_8bit = (current_bitmask & bitmask) >> current_shift; + this->push_back(value_8bit); + } +} + +//////////////////////////////////////////////////////////////////////////////////// +// Attribute store helpers +//////////////////////////////////////////////////////////////////////////////////// +void helper_set_version(const zwave_cc_version_t &version) +{ + cpp_endpoint_id_node.add_node(current_command_class_id << 8 | 0x01) + .set_reported(version); +} + +zwave_cc_version_t helper_get_version() +{ + return zwave_command_class_get_version_from_node(cpp_endpoint_id_node, + current_command_class_id); +} + +//////////////////////////////////////////////////////////////////////////////////// +// Helpers +//////////////////////////////////////////////////////////////////////////////////// +void helper_test_handler(const zwave_struct_handler_args &args) +{ + TEST_ASSERT_EQUAL_MESSAGE(args.scheme, + handler.minimal_scheme, + "Minimal scheme mismatch in handler"); + TEST_ASSERT_EQUAL_MESSAGE(args.command_class_id, + handler.command_class, + "Command class mismatch in handler"); + TEST_ASSERT_EQUAL_MESSAGE(args.supported_version, + handler.version, + "Version mismatch in handler"); + + if (args.has_control_handler) { + TEST_ASSERT_NOT_NULL_MESSAGE(handler.control_handler, + "Handler should have control handler"); + } else { + TEST_ASSERT_NULL_MESSAGE(handler.control_handler, + "Handler should NOT have control handler"); + } + + if (args.has_support_handler) { + TEST_ASSERT_NOT_NULL_MESSAGE(handler.support_handler, + "Handler should have support handler"); + } else { + TEST_ASSERT_NULL_MESSAGE(handler.support_handler, + "Handler should NOT have support handler"); + } + + TEST_ASSERT_FALSE(handler.manual_security_validation); +} + +void helper_test_get_set_frame_happy_case(uint8_t command_id, + attribute_store_node_t base_node, + const std::vector &args) +{ + auto &resolver_function + = resolver_function_helper.get_resolver_function(command_id); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + resolver_function(base_node, received_frame, &received_frame_size), + (boost::format("Set/Get command '0x%02x' should have worked") + % unsigned(command_id)) + .str() + .c_str()); + + // Construct frame + std::vector expected_frame = {current_command_class_id, command_id}; + expected_frame.insert(expected_frame.end(), args.cbegin(), args.cend()); + + TEST_ASSERT_EQUAL_MESSAGE( + expected_frame.size(), + received_frame_size, + (boost::format("Frame size is incorrect for set/get command '0x%02x'") + % unsigned(command_id)) + .str() + .c_str()); + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE( + expected_frame.data(), + received_frame, + received_frame_size, + (boost::format("Frame contents mismatch for set/get command '0x%02x'") + % unsigned(command_id)) + .str() + .c_str()); +} + +void helper_test_get_set_fail_case(uint8_t command_id, + sl_status_t expected_status, + attribute_store_node_t base_node) +{ + auto &resolver_function + = resolver_function_helper.get_resolver_function(command_id); + + TEST_ASSERT_EQUAL_MESSAGE( + expected_status, + resolver_function(base_node, received_frame, &received_frame_size), + (boost::format("Set/Get command '0x%02x' should NOT have worked") + % unsigned(command_id)) + .str() + .c_str()); +} + +void helper_test_report_frame(uint8_t command_id, + const std::vector &args, + sl_status_t expected_status) +{ + std::vector report_frame = {current_command_class_id, command_id}; + report_frame.insert(report_frame.end(), args.cbegin(), args.cend()); + + TEST_ASSERT_NOT_NULL_MESSAGE(handler.control_handler, + "Control handler should be defined. Check that you've call zwave_setUp() and you linked the mock libraries against this test."); + sl_status_t result = handler.control_handler(&mock_connection_info, + report_frame.data(), + report_frame.size()); + + std::string debug_message + = expected_status == SL_STATUS_OK + ? "Report frame (0x%02x) should have worked" + : "Report frame (0x%02x) should NOT have worked"; + debug_message = (boost::format(debug_message) % unsigned(command_id)).str(); + + TEST_ASSERT_EQUAL_MESSAGE(expected_status, result, debug_message.c_str()); +} + +void helper_test_node_existence(attribute_store::attribute attribute, + bool should_exists, + const std::string &expected_attribute_name, + const std::string &expected_parent_name) +{ + TEST_ASSERT_EQUAL_MESSAGE( + should_exists, + attribute.is_valid(), + (boost::format("Attribute '%1%' should %2% exists under '%3%'") + % expected_attribute_name % (should_exists ? "" : "NOT") + % expected_parent_name) + .str() + .c_str()); +} + +attribute_store::attribute + helper_test_and_get_node(attribute_store_type_t node_type, + attribute_store::attribute parent) +{ + auto attribute = parent.child_by_type(node_type); + + helper_test_node_existence(attribute, + true, + attribute_store_get_type_name(node_type), + parent.name()); + return attribute; +} + +void helper_test_node_exists(attribute_store_type_t node_type, + attribute_store::attribute parent) +{ + helper_test_node_existence(parent.child_by_type(node_type), + true, + attribute_store_get_type_name(node_type), + parent.name()); +} +void helper_test_node_does_not_exists(attribute_store_type_t node_type, + attribute_store::attribute parent) +{ + helper_test_node_existence(parent.child_by_type(node_type), + false, + attribute_store_get_type_name(node_type), + parent.name()); +} + +} // namespace zwave_command_class_test_helper +} // extern "C" \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/test/helpers/zwave_command_class_test_helper.hpp b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_command_class_test_helper.hpp new file mode 100644 index 0000000000..b9ca343bad --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_command_class_test_helper.hpp @@ -0,0 +1,391 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef ZWAVE_COMMAND_CLASS_TEST_HELPER_HPP +#define ZWAVE_COMMAND_CLASS_TEST_HELPER_HPP + +// Note : +// Put c++ includes here, and C includes below extern "C" to avoid error +// "error while loading shared libraries: unexpected PLT reloc type 0x00" + +// Unify cpp +#include "attribute.hpp" +#include "zwave_resolver_function_helper.hpp" + +// C++ includes +#include +#include + +extern "C" { +// Test framework +#include "unity.h" + +// Helper class +#include "zpc_attribute_store_test_helper.h" + +// Unify +#include "zwave_command_handler.h" + +namespace zwave_command_class_test_helper +{ +//////////////////////////////////////////////////////////////////////////////////// +// Alias +//////////////////////////////////////////////////////////////////////////////////// +using command_class_init_function = std::function; + +//////////////////////////////////////////////////////////////////////////////////// +// Struct +//////////////////////////////////////////////////////////////////////////////////// +struct zwave_struct_handler_args { + zwave_command_class_t command_class_id; + zwave_cc_version_t supported_version; + zwave_controller_encapsulation_scheme_t scheme + = ZWAVE_CONTROLLER_ENCAPSULATION_NETWORK_SCHEME; + bool has_control_handler = true; + bool has_support_handler = false; +}; + +//////////////////////////////////////////////////////////////////////////////////// +// CONST +//////////////////////////////////////////////////////////////////////////////////// +static const uint8_t MAX_CHAR_SIZE = 64; + +//////////////////////////////////////////////////////////////////////////////////// +// Global variables +// Must be declared as "extern" and defined in the cpp to avoid multiple definition +// More information : https://stackoverflow.com/questions/11478152/how-to-work-with-variable-in-namespace +//////////////////////////////////////////////////////////////////////////////////// + +// Buffers for frame. We use a static C array here to match the C API +extern uint8_t received_frame[255]; +extern uint16_t received_frame_size; +// ZWave current command handler +extern zwave_command_handler_t handler; +// Resolver function helper +extern zwave_resolver_function_helper resolver_function_helper; + +// Current current command class id. We use uint8_t here instead of zwave_command_class_t to be able to set it directly in the tested frames. +extern uint8_t current_command_class_id; +// Endpoint id node wrapper +extern attribute_store::attribute cpp_endpoint_id_node; +// Used for report frames +extern zwave_controller_connection_info_t mock_connection_info; + +//////////////////////////////////////////////////////////////////////////////////// +// Suit setup +//////////////////////////////////////////////////////////////////////////////////// +/** + * @brief Setup the Z-Wave test suite + * + * It will setup all the variables needed for the tests. + * + * @code + * // Tested command class handler + const zwave_struct_handler_args command_class_handler + = {.command_class_id = COMMAND_CLASS_SWITCH_BINARY, // Will be stored in current_command_class_id + .supported_version = 2, + .scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NONE}; + // Get Set function map + const resolver_function_map attribute_bindings = { + {ATTRIBUTE(VALUE), {SWITCH_BINARY_GET, SWITCH_BINARY_SET}}, + }; + + /// Called before each and every test + void setUp() + { + zwave_setUp(command_class_handler, + &zwave_command_class_binary_switch_init, + attribute_bindings); + } + * @endcode + * + * One the initial setup is done, you can use all the function in the namespace to help you : + * This function will call the resolver function you've set with attribute_bindings and check it return value. + * + * @code + void test_binary_switch_get_happy_case() + { + helper_test_get_set_frame_happy_case(SWITCH_BINARY_GET); + } + * @endcode + * + * @param args Test data against the zwave handler. Checks command class, version, handlers... + * @param init_function The function to call to initialize the command class. Check if it returns SL_STATUS_OK. + * @param bindings The resolver functions to bind to the command class. Allows to use helper_test_get_set_frame_happy_case() helpers functions + * + */ +void zwave_setUp(const zwave_struct_handler_args &args, + const command_class_init_function &init_function, + const resolver_function_map &bindings = {}); + +//////////////////////////////////////////////////////////////////////////////////// +// Stub defintions +//////////////////////////////////////////////////////////////////////////////////// +/** + * @brief Associated callback for zwave_command_handler_register_handler_Stub + */ +sl_status_t zwave_command_handler_register_handler_stub( + zwave_command_handler_t new_command_class_handler, int cmock_num_calls); + +/** + * @brief Associated callback for attribute_resolver_register_rule_Stub + */ +sl_status_t + attribute_resolver_register_rule_stub(attribute_store_type_t node_type, + attribute_resolver_function_t set_func, + attribute_resolver_function_t get_func, + int cmock_num_calls); + +//////////////////////////////////////////////////////////////////////////////////// +// Frame generation helpers +//////////////////////////////////////////////////////////////////////////////////// +/** + * @brief Helper to generate a frame contents. Can be used to generate + * any zwave_frame and test it. + * + * @note This class inherits from vector directly. + **/ +class zwave_frame : public std::vector { + public: + zwave_frame() = default; + /** + * @brief Add a byte to the frame + * + * @param byte Byte to add + */ + void add(uint8_t byte); + /** + * @brief Add a 16 bits value to the frame (msb first, lsb second) + * + * @param value Value to add + */ + void add(uint16_t value); + /** + * @brief Add a 32 bits value to the frame (msb first, lsb last) + * + * @param value Value to add + */ + void add(uint32_t value); + /** + * @brief Add a string to the frame (with its size before, without NULL terminator) + * + * > String size N + * > Char 1 + * > Char 2 + * > ... + * > Char N + * + * @param value String to add + */ + void add(const std::string &value); + /** + * @brief Add a vector of bytes to the frame (with its size before) + * + * > Vector size N + * > Byte 1 + * > Byte 2 + * > ... + * > Byte N + * + * @param bytes Bytes to add + */ + void add(const std::vector &bytes); + + /** + * @brief Add a ZWave bitmask to the frame (with its size before, lsb first msb last) + * + * > Bitmask size N + * > Bitmask first byte (LSB) + * > Bitmask second byte + * > ... + * > Bitmask N byte (MSB) + * + * @param size Size of the bitmask + * @param bitmask Bitmask to add + */ + void add_bitmask(uint8_t size, uint32_t bitmask); +}; + +//////////////////////////////////////////////////////////////////////////////////// +// Attribute store helpers +//////////////////////////////////////////////////////////////////////////////////// +/** + * @brief Set version for current class + * + * @note Use current_command_class_id global variable to determine the current current class + * + * @brief Command class version + */ +void helper_set_version(const zwave_cc_version_t &version); + +/** + * @brief Get version for current class + * + * @note Use current_command_class_id global variable to determine the current current class + * + * @return Command class version + */ +zwave_cc_version_t helper_get_version(); + +//////////////////////////////////////////////////////////////////////////////////// +// Global Test Helpers +//////////////////////////////////////////////////////////////////////////////////// +/** + * @brief Test current handler with given arguments + * + * Make the test fail if any value in the struct doesn't match the handler value + * + * @param args Test data against the zwave handler. Checks all the paramaters in the struct + * + */ +void helper_test_handler(const zwave_struct_handler_args &args); + +//////////////////////////////////////////////////////////////////////////////////// +// Get/Set Test Helpers +//////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Call get/set function and check the frame contents and return value (SL_STATUS_OK) + * + * This function will check internally the associated function with given command_id. + * It will then call it with the given base_node and checks the frame contents. + * The function needs to return SL_STATUS_OK to pass the test. + * + * @note Only works correctly if you've set the bindings in zwave_setUp() + * + * @param command_id Command id to test + * @param base_node Base node that will be given to the resolver function + * @param args Expected frame contents after {current_command_class_id, command_id}. Can be left empty. + */ +void helper_test_get_set_frame_happy_case(uint8_t command_id, + attribute_store_node_t base_node + = ATTRIBUTE_STORE_INVALID_NODE, + const std::vector &args + = {}); + +/** + * @brief Call get/set function and check that it has failed + * + * This function will check internally the associated function with given command_id. + * It will then call it with the given base_node and checks the return value. + * The function needs to return the expected_status to pass the test. + * + * @note Only works correctly if you've set the bindings in zwave_setUp() + * + * @param command_id Command id to test + * @param expected_status Expected return value of the function + * @param base_node Base node that will be given to the resolver function + */ +void helper_test_get_set_fail_case(uint8_t command_id, + sl_status_t expected_status + = SL_STATUS_NOT_SUPPORTED, + attribute_store_node_t base_node + = ATTRIBUTE_STORE_INVALID_NODE); + +//////////////////////////////////////////////////////////////////////////////////// +// Report Test Helpers +//////////////////////////////////////////////////////////////////////////////////// + +/** + * @brief Call report function with given frame and check it return status + * + * @param command_id Command id to test + * @param args Frame contents after {current_command_class_id, command_id} + * @param expected_status Expected return value of the function + */ +void helper_test_report_frame(uint8_t command_id, + const std::vector &args, + sl_status_t expected_status = SL_STATUS_OK); + +//////////////////////////////////////////////////////////////////////////////////// +// Node/Attribute Test Helpers +//////////////////////////////////////////////////////////////////////////////////// +/** + * @brief Get a node and check that it exists + * + * @note Test will fail if node doesn't exists + * + * @param node_type Node type to get + * @param parent Parent node of the node to get (default to current endpoint) + * + * @return attribute_store::attribute Node that was found (garmented to exists) + */ +attribute_store::attribute + helper_test_and_get_node(attribute_store_type_t node_type, + attribute_store::attribute parent + = cpp_endpoint_id_node); + +/** + * @brief Test that a node exists + * + * @param node_type Node type to test + * @param parent Parent node of the node to get (default to current endpoint) + */ +void helper_test_node_exists(attribute_store_type_t node_type, + attribute_store::attribute parent + = cpp_endpoint_id_node); +/** + * @brief Test that a node doesn't exists + * + * @param node_type Node type to test + * @param parent Parent node of the node to get (default to current endpoint) + */ +void helper_test_node_does_not_exists(attribute_store_type_t node_type, + attribute_store::attribute parent + = cpp_endpoint_id_node); + +} // namespace zwave_command_class_test_helper + +} // extern "C" + +// Cpp template functions +namespace zwave_command_class_test_helper +{ +template attribute_store::attribute helper_test_attribute_value( + attribute_store_type_t node_type, + T expected_value, + attribute_store::attribute parent = cpp_endpoint_id_node, + attribute_store_node_value_state_t state = REPORTED_ATTRIBUTE) +{ + auto current_node = helper_test_and_get_node(node_type, parent); + + try { + const std::string error_message + = (std::string("Value mismatch for ") + current_node.name_and_id()) + .c_str(); + + if constexpr (std::is_same>::value) { + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE( + expected_value.data(), + current_node.reported>().data(), + expected_value.size(), + error_message.c_str()); + } else if constexpr (std::is_same::value) { + TEST_ASSERT_EQUAL_STRING_MESSAGE( + expected_value.c_str(), + current_node.reported().c_str(), + error_message.c_str()); + } else { + TEST_ASSERT_EQUAL_MESSAGE(expected_value, + current_node.get(state), + error_message.c_str()); + } + } catch (std::exception &e) { + TEST_FAIL_MESSAGE(e.what()); + } + + return current_node; +} +} // namespace zwave_command_class_test_helper + +#endif // ZWAVE_COMMAND_CLASS_TEST_HELPER_HPP \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_test_helper.c b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_raw_frame_test_helper.c similarity index 99% rename from applications/zpc/components/zwave_command_classes/test/zwave_command_class_test_helper.c rename to applications/zpc/components/zwave_command_classes/test/helpers/zwave_raw_frame_test_helper.c index a08bc079fc..f243a2748a 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_test_helper.c +++ b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_raw_frame_test_helper.c @@ -14,7 +14,7 @@ // Test includes #include "unity.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" // Mock includes #include "zwave_tx_scheme_selector_mock.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_test_helper.h b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_raw_frame_test_helper.h similarity index 96% rename from applications/zpc/components/zwave_command_classes/test/zwave_command_class_test_helper.h rename to applications/zpc/components/zwave_command_classes/test/helpers/zwave_raw_frame_test_helper.h index 84e6c47aba..a799534dd6 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_test_helper.h +++ b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_raw_frame_test_helper.h @@ -11,8 +11,8 @@ * *****************************************************************************/ -#ifndef ZWAVE_COMMAND_CLASS_TEST_HELPER_H -#define ZWAVE_COMMAND_CLASS_TEST_HELPER_H +#ifndef ZWAVE_RAW_FRAME_TEST_HELPER_H +#define ZWAVE_RAW_FRAME_TEST_HELPER_H #include "sl_status.h" #include "zwave_controller_connection_info.h" diff --git a/applications/zpc/components/zwave_command_classes/test/helpers/zwave_resolver_function_helper.cpp b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_resolver_function_helper.cpp new file mode 100644 index 0000000000..1861447ea9 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_resolver_function_helper.cpp @@ -0,0 +1,85 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +// Base class +#include "zwave_resolver_function_helper.hpp" + +// Unify +#include "sl_status.h" + +// C++ includes +#include + +// Test fuctions +#include "unity.h" + +extern "C" { +namespace zwave_command_class_test_helper +{ + +void zwave_resolver_function_helper::set_resolver_functions( + const resolver_function_map &bindings) +{ + attributes_binding = bindings; + // Clear previous resolver functions + resolver_functions.clear(); +}; + +sl_status_t zwave_resolver_function_helper::register_resolver_functions( + attribute_store_type_t node_type, + attribute_resolver_function_t set_func, + attribute_resolver_function_t get_func) +{ + std::string message; + std::string node_name = attribute_store_get_type_name(node_type); + + if (attributes_binding.find(node_type) != attributes_binding.end()) { + const auto func = attributes_binding.at(node_type); + + if (func.get_func_id == 0) { + message = "GET function should not be defined for " + node_name + + ". Did you forget to add it to the binding attribute ?"; + TEST_ASSERT_NULL_MESSAGE(get_func, message.c_str()); + } else { + message = "SET function should be defined for " + node_name + + ". Did you forget to remove it to the binding attribute ?"; + TEST_ASSERT_NOT_NULL_MESSAGE(get_func, message.c_str()); + resolver_functions[func.get_func_id] = get_func; + } + + if (func.set_func_id == 0) { + message = "SET function should not be defined for " + node_name + + ". Did you forget to add it to the binding attribute ?"; + TEST_ASSERT_NULL_MESSAGE(set_func, message.c_str()); + } else { + message = "SET function should be defined for " + node_name + + ". Did you forget to remove it to the binding attribute ?"; + TEST_ASSERT_NOT_NULL_MESSAGE(set_func, message.c_str()); + resolver_functions[func.set_func_id] = set_func; + } + } + + return SL_STATUS_OK; +} + +attribute_resolver_function_t & + zwave_resolver_function_helper::get_resolver_function(uint8_t function_id) +{ + if (resolver_functions.find(function_id) == resolver_functions.end()) { + TEST_FAIL_MESSAGE("Resolver function not found."); + } + + return resolver_functions[function_id]; +} + +} // namespace zwave_command_class_test_helper +} // extern "C" \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/test/helpers/zwave_resolver_function_helper.hpp b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_resolver_function_helper.hpp new file mode 100644 index 0000000000..65b7d86808 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/helpers/zwave_resolver_function_helper.hpp @@ -0,0 +1,174 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ + +#ifndef ZWAVE_RESOLVER_FUNCTION_HELPER_HPP +#define ZWAVE_RESOLVER_FUNCTION_HELPER_HPP + +// C++ includes +#include +#include + +// Unify +#include "attribute_store.h" +#include "attribute_store_type_registration.h" +#include "attribute_resolver.h" + +extern "C" { +namespace zwave_command_class_test_helper +{ + +/** + * @brief Z-Wave functions ID + * + * @warning This implementation assumes that the ID are all > 0 + */ +struct zwave_functions { + uint8_t get_func_id; + uint8_t set_func_id; +}; + +/** + * @brief Map of attribute type to resolver functions + * + * If you have declared in your command class : + * + * @code{.cpp} + attribute_resolver_register_rule(ATTRIBUTE(VALUE), + zwave_command_class_binary_switch_set, + zwave_command_class_binary_switch_get); + * @endcode + * + * You can bind the functions like this : + * + * @code{.cpp} + resolver_helper.set_resolver_functions({ + {ATTRIBUTE(VALUE), {SWITCH_BINARY_GET, SWITCH_BINARY_SET}}, + }; + * @endcode + * + * This way you'll be able to get the get/set functions with the function id : + * + * @code{.cpp} + // Call the function zwave_command_class_binary_switch_get + auto get_func = resolver_helper.get_resolver_function(SWITCH_BINARY_GET); + * @endcode + * + */ +using resolver_function_map = std::map; + +/** + * @brief Helper class to manage resolver functions + * + * @note This class isn't meant for you to use directly on your tests. + * Use the top level wrapper zwave_command_class_test_helper instead. + * + * @warning This class can only register Get/Set function that are in the same + * Command Class. Otherwise ID will overlap. + * + * This class allows you to get the get or set functions for a given attribute. + * It allows you to test easily the resolver functions. + * + * First setup your resolver functions bindings : + * + * @code{.cpp} + * + * zwave_resolver_function_helper resolver_helper; + * + * resolver_helper.set_resolver_functions({ + * {ATTRIBUTE(NUMBER_OF_USERS), {USER_CAPABILITIES_GET, 0}}, + * {ATTRIBUTE(USER_UNIQUE_ID), {USER_GET, USER_SET}}, + * }); + * @endcode + * + * In attribute_resolver_register_rule_stub callback : + * + * @code{.cpp} + * sl_status_t + * attribute_resolver_register_rule_stub(attribute_store_type_t node_type, + * attribute_resolver_function_t set_func, + * attribute_resolver_function_t get_func, + * int cmock_num_calls) + * { + * return resolver_function_helper.register_resolver_functions(node_type, + * set_func, + * get_func); + * } + * @endcode + * + * Then you can get your set/get function with : + * + * @code{.cpp} + * auto user_get = resolver_function_helper.get_resolver_function(USER_GET); + * user_get(current_node, frame, &frame_size); // Will call the get function of the command class + * + * // Will make the test fail since USER_CAPABILITIES_SET is not bound + * // resolver_function_helper.get_resolver_function(USER_CAPABILITIES_SET); + * @endcode + * + */ +class zwave_resolver_function_helper +{ + public: + /** + * @brief Set the resolver functions bindings that will be used to register the resolver functions + * + * @param bindings Functions bindings. See class description to know how to use it + * + * @note This function should be called before calling register_resolver_functions + * + * @see register_resolver_functions + */ + void set_resolver_functions(const resolver_function_map &bindings); + + /** + * @brief Register the resolver functions for a given node type + * + * The node_type, set_func and get_func arguments match the ones + * in attribute_resolver_register_rule_stub + * + * @note Use the bindings set with set_resolver_functions to register the functions + * + * @param node_type Node type to register the functions + * @param set_func Function to set the attribute value + * @param get_func Function to get the attribute value + * + * @return sl_status_t SL_STATUS_OK if the functions were registered successfully + * + */ + sl_status_t + register_resolver_functions(attribute_store_type_t node_type, + attribute_resolver_function_t set_func, + attribute_resolver_function_t get_func); + + /** + * @brief Get the resolver function for a given function id + * + * The test will automatically fails if the binding doesn't exists. + * + * @note This function should be called after calling register_resolver_functions, or it will always fails + * + * @param function_id Function id to get + * + * @return attribute_resolver_function_t& The resolver function + */ + attribute_resolver_function_t &get_resolver_function(uint8_t function_id); + + private: + resolver_function_map attributes_binding; + std::map resolver_functions; + +}; // class zwave_resolver_function_helper +} // namespace zwave_command_class_test_helper +} // extern "C" + +#endif // ZWAVE_RESOLVER_FUNCTION_HELPER_HPP diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c index b47a8c93c3..779aa687ed 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c @@ -20,7 +20,7 @@ // Includes from this component #include "zwave_command_class_indicator.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" // Includes from other components #include "zwave_controller_connection_info.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c.rej b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c.rej new file mode 100644 index 0000000000..ebfa5db859 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c.rej @@ -0,0 +1,10 @@ +diff a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_indicator_test.c (rejected hunks) +@@ -20,7 +20,7 @@ + + // Includes from this component + #include "zwave_command_class_indicator.h" +-#include "zwave_command_class_test_helper.h" ++#include "zwave_raw_frame_test_helper.h" + + // Includes from other components + #include "zwave_controller_connection_info.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c index 2d0ce99254..24c291a357 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c @@ -12,7 +12,7 @@ *****************************************************************************/ // Includes from this component #include "zwave_command_class_manufacturer_specific.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" #define MANUFACTURER_ID 0x1234 #define PRODUCT_TYPE 0x5678 diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c.rej b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c.rej new file mode 100644 index 0000000000..113c431029 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c.rej @@ -0,0 +1,10 @@ +diff a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_manufacturer_specific_test.c (rejected hunks) +@@ -12,7 +12,7 @@ + *****************************************************************************/ + // Includes from this component + #include "zwave_command_class_manufacturer_specific.h" +-#include "zwave_command_class_test_helper.h" ++#include "zwave_raw_frame_test_helper.h" + + #define MANUFACTURER_ID 0x1234 + #define PRODUCT_TYPE 0x5678 diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c index 2ee0970d93..073e598277 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c @@ -12,7 +12,7 @@ *****************************************************************************/ // Includes from this component #include "zwave_command_class_notification.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" // Generic includes #include // for memset diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c.rej b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c.rej new file mode 100644 index 0000000000..350bee07a6 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c.rej @@ -0,0 +1,10 @@ +diff a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_notification_test.c (rejected hunks) +@@ -12,7 +12,7 @@ + *****************************************************************************/ + // Includes from this component + #include "zwave_command_class_notification.h" +-#include "zwave_command_class_test_helper.h" ++#include "zwave_raw_frame_test_helper.h" + + // Generic includes + #include // for memset diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c index 26ab44bf16..351043d4d8 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c @@ -12,7 +12,7 @@ *****************************************************************************/ #include "zwave_command_class_powerlevel.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" // Includes from other components #include "zwave_tx_mock.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c.rej b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c.rej new file mode 100644 index 0000000000..779fd2f29a --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c.rej @@ -0,0 +1,10 @@ +diff a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_powerlevel_test.c (rejected hunks) +@@ -12,7 +12,7 @@ + *****************************************************************************/ + + #include "zwave_command_class_powerlevel.h" +-#include "zwave_command_class_test_helper.h" ++#include "zwave_raw_frame_test_helper.h" + + // Includes from other components + #include "zwave_tx_mock.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c index 9b3276af55..a780377e04 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c @@ -16,7 +16,7 @@ // Includes from this component #include "zwave_command_class_time.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" // Includes from other components #include "zwave_tx_mock.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c.rej b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c.rej new file mode 100644 index 0000000000..23258a79ce --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c.rej @@ -0,0 +1,10 @@ +diff a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_time_test.c (rejected hunks) +@@ -16,7 +16,7 @@ + + // Includes from this component + #include "zwave_command_class_time.h" +-#include "zwave_command_class_test_helper.h" ++#include "zwave_raw_frame_test_helper.h" + + // Includes from other components + #include "zwave_tx_mock.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_user_credential_test.cpp b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_user_credential_test.cpp new file mode 100644 index 0000000000..71f2fc65a5 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_user_credential_test.cpp @@ -0,0 +1,4489 @@ +/****************************************************************************** + * # License + * Copyright 2024 Silicon Laboratories Inc. www.silabs.com + ****************************************************************************** + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + *****************************************************************************/ +#include +#include "workaround_for_test.hpp" +#include "attribute.hpp" + +// Test helpers +#include "zwave_command_class_test_helper.hpp" + +using namespace zwave_command_class_test_helper; + +extern "C" { + +#include "zwave_command_class_user_credential.h" +#include "zwave_command_class_user_credential_api.h" +#include "zwave_command_class_user_credential_types.h" +#include "zwave_command_classes_utils.h" +#include "unity.h" + +// Generic includes +#include + +// Includes from other components +#include "datastore.h" +#include "attribute_store.h" +#include "attribute_store_helper.h" +#include "attribute_store_fixt.h" +#include "attribute_store_type_registration.h" +#include "zpc_attribute_store_type_registration.h" + +// Interface includes +#include "attribute_store_defined_attribute_types.h" +#include "ZW_classcmd.h" +#include "zwave_utils.h" +#include "zwave_controller_types.h" + +// Mock includes +#include "attribute_resolver_mock.h" +#include "zpc_attribute_resolver_mock.h" +#include "zwave_command_handler_mock.h" +#include "dotdot_mqtt_mock.h" +#include "dotdot_mqtt_generated_commands_mock.h" +#include "zwave_command_class_notification_mock.h" + +// Used for delayed interview +#include "zwave_network_management_mock.h" + +#define ATTRIBUTE(type) ATTRIBUTE_COMMAND_CLASS_USER_CREDENTIAL_##type + +const resolver_function_map attributes_binding + = {{ATTRIBUTE(NUMBER_OF_USERS), {USER_CAPABILITIES_GET, 0}}, + {ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM), {CREDENTIAL_CAPABILITIES_GET, 0}}, + {ATTRIBUTE(ALL_USERS_CHECKSUM), {ALL_USERS_CHECKSUM_GET, 0}}, + {ATTRIBUTE(USER_UNIQUE_ID), {USER_GET, 0}}, + {ATTRIBUTE(USER_OPERATION_TYPE), {0, USER_SET}}, + {ATTRIBUTE(CREDENTIAL_SLOT), {CREDENTIAL_GET, 0}}, + {ATTRIBUTE(CREDENTIAL_OPERATION_TYPE), {0, CREDENTIAL_SET}}, + {ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE), {0, CREDENTIAL_LEARN_START}}, + {ATTRIBUTE(CREDENTIAL_LEARN_STOP), {0, CREDENTIAL_LEARN_CANCEL}}, + {ATTRIBUTE(ASSOCIATION_DESTINATION_CREDENTIAL_SLOT), + {0, USER_CREDENTIAL_ASSOCIATION_SET}}, + {ATTRIBUTE(USER_CHECKSUM), {USER_CHECKSUM_GET, 0}}, + {ATTRIBUTE(CREDENTIAL_CHECKSUM), {CREDENTIAL_CHECKSUM_GET, 0}}, + {ATTRIBUTE(ADMIN_PIN_CODE), {ADMIN_PIN_CODE_GET, ADMIN_PIN_CODE_SET}}}; + +// Tested command class handler +const zwave_struct_handler_args command_class_handler + = {.command_class_id = COMMAND_CLASS_USER_CREDENTIAL, + .supported_version = USER_CREDENTIAL_VERSION, + .scheme = ZWAVE_CONTROLLER_ENCAPSULATION_SECURITY_2_ACCESS}; + +///////////////////////////////////////////////////// +// HELPERS +///////////////////////////////////////////////////// +struct credential_structure_nodes { + attribute_store::attribute user_id_node; + attribute_store::attribute credential_type_node; + attribute_store::attribute credential_slot_node; + + void print() + { + printf("%s / %s / %s\n", + user_id_node.name_and_id().c_str(), + credential_type_node.name_and_id().c_str(), + credential_slot_node.name_and_id().c_str()); + }; +}; + +/** + * @brief Create credential structure and return associated nodes + * + * @param user_id + * @param credential_type + * @param credential_slot + * @param value_state If DESIRED_ATTRIBUTE : credential_type/credential_slot will have their desired value setup, reported otherwise + * @return credential_structure_nodes + */ +credential_structure_nodes helper_create_credential_structure( + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + attribute_store_node_value_state_t value_state = DESIRED_ATTRIBUTE) +{ + credential_structure_nodes nodes; + + nodes.user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + nodes.credential_type_node + = nodes.user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type); + + nodes.credential_slot_node + = nodes.credential_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + value_state); + + return nodes; +} + +//////////////////////////////////////////////////// +// Report helpers +//////////////////////////////////////////////////// + +void helper_simulate_user_capabilites_report( + uint16_t number_of_users, + user_credential_supported_credential_rules_t cred_rule_bitmask, + uint8_t username_max_length, + uint8_t support_user_schedule, + uint8_t support_all_users_checksum, + uint8_t support_user_checksum, + uint8_t supported_user_types_bitmask_length, + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask) +{ + zwave_frame report_frame; + + report_frame.add(number_of_users); + report_frame.add(cred_rule_bitmask); + report_frame.add(username_max_length); + uint8_t support_byte = (support_user_schedule << 7) + | (support_all_users_checksum << 6) + | (support_user_checksum << 5); + report_frame.add(support_byte); + report_frame.add_bitmask(supported_user_types_bitmask_length, + supported_user_types_bitmask); + + // Add bitmask value + helper_test_report_frame(USER_CAPABILITIES_REPORT, report_frame); +} + +void helper_simulate_credential_capabilites_report( + uint8_t credential_checksum_support, + uint8_t admin_code_support, + uint8_t admin_code_deactivation_support, + std::vector credential_type, + std::vector cl_support, + std::vector supported_credential_slots, + std::vector min_length, + std::vector max_length, + std::vector cl_timeout, + std::vector cl_steps) +{ + if (credential_type.size() != cl_support.size() + || credential_type.size() != supported_credential_slots.size() + || credential_type.size() != min_length.size() + || credential_type.size() != max_length.size() + || credential_type.size() != cl_timeout.size() + || credential_type.size() != cl_steps.size()) { + TEST_FAIL_MESSAGE("Size of credential_type, cl_support, " + "supported_credential_slots, min_length, max_length, " + "cl_timeout and cl_steps" + "should be the same."); + } + + zwave_frame report_frame; + + report_frame.add(static_cast( + credential_checksum_support << 7 | admin_code_support << 6 + | admin_code_deactivation_support << 5)); + report_frame.add(static_cast(credential_type.size())); + + for (auto &c: credential_type) { + report_frame.add(c); + } + for (auto &cl: cl_support) { + report_frame.add(static_cast(cl << 7)); + } + for (auto &c: supported_credential_slots) { + report_frame.add(c); + } + for (auto &c: min_length) { + report_frame.add(c); + } + for (auto &c: max_length) { + report_frame.add(c); + } + for (auto &c: cl_timeout) { + report_frame.add(c); + } + for (auto &c: cl_steps) { + report_frame.add(c); + } + + helper_test_report_frame(CREDENTIAL_CAPABILITIES_REPORT, report_frame); +}; + +void helper_simulate_user_checksum_report( + user_credential_user_unique_id_t user_id, + user_credential_checksum_t expected_checksum, + sl_status_t expected_status = SL_STATUS_OK) +{ + zwave_frame report_frame; + report_frame.add(user_id); + report_frame.add(expected_checksum); + + helper_test_report_frame(USER_CHECKSUM_REPORT, report_frame, expected_status); +} + +void helper_simulate_credential_checksum_report( + user_credential_type_t credential_type, + user_credential_checksum_t expected_checksum, + sl_status_t expected_status = SL_STATUS_OK) +{ + zwave_frame report_frame; + report_frame.add(credential_type); + report_frame.add(expected_checksum); + + helper_test_report_frame(CREDENTIAL_CHECKSUM_REPORT, + report_frame, + expected_status); +} + +void helper_simulate_learn_status_report_frame( + uint8_t credential_learn_status, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + uint8_t learn_steps_remaining) +{ + zwave_frame report_frame; + + report_frame.add(credential_learn_status); + report_frame.add(user_id); + report_frame.add(credential_type); + report_frame.add(credential_slot); + report_frame.add(learn_steps_remaining); + + helper_test_report_frame(CREDENTIAL_LEARN_REPORT, report_frame); +} + +void helper_simulate_association_report_frame( + user_credential_user_unique_id_t source_user_id, + user_credential_type_t source_credential_type, + user_credential_slot_t source_credential_slot, + user_credential_user_unique_id_t destination_user_id, + user_credential_slot_t destination_credential_slot, + uint8_t credential_association_status, + sl_status_t expected_status = SL_STATUS_OK) +{ + zwave_frame report_frame; + + report_frame.add(source_user_id); + report_frame.add(source_credential_type); + report_frame.add(source_credential_slot); + report_frame.add(destination_user_id); + report_frame.add(destination_credential_slot); + report_frame.add(credential_association_status); + + helper_test_report_frame(USER_CREDENTIAL_ASSOCIATION_REPORT, + report_frame, + expected_status); +} + +void helper_test_credential_learn_structure( + attribute_store::attribute user_id_node, + attribute_store::attribute credential_type_node, + attribute_store::attribute credential_slot_node, + user_credential_learn_timeout_t expected_cl_timeout, + user_credential_operation_type_t expected_operation_type) +{ + TEST_ASSERT_TRUE_MESSAGE(user_id_node.is_valid(), + "Credential type node should exist"); + TEST_ASSERT_TRUE_MESSAGE(credential_type_node.is_valid(), + "Credential type node should exist"); + TEST_ASSERT_TRUE_MESSAGE(credential_slot_node.is_valid(), + "Credential type slot should exist"); + + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_LEARN_TIMEOUT), + expected_cl_timeout, + credential_slot_node); + + auto operation_type_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_LEARN_OPERATION_TYPE), + expected_operation_type, + credential_slot_node, + DESIRED_ATTRIBUTE); + + user_credential_user_unique_id_t user_id + = user_id_node.reported(); + user_credential_type_t credential_type + = credential_type_node.reported(); + user_credential_slot_t credential_slot + = credential_slot_node.reported(); + + zwave_frame learn_start_frame; + learn_start_frame.add(user_id); + learn_start_frame.add(credential_type); + learn_start_frame.add(credential_slot); + learn_start_frame.add(expected_operation_type); + learn_start_frame.add(expected_cl_timeout); + + helper_test_get_set_frame_happy_case(CREDENTIAL_LEARN_START, + operation_type_node, + learn_start_frame); + + uint8_t step_remaining = 2; + user_credential_learn_status_t learn_status = CREDENTIAL_LEARN_REPORT_SUCCESS; + helper_simulate_learn_status_report_frame(learn_status, + user_id, + credential_type, + credential_slot, + step_remaining); + + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_LEARN_STATUS), + learn_status, + credential_slot_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_LEARN_STEPS_REMAINING), + step_remaining, + credential_slot_node); +}; + +struct association_nodes_t { + attribute_store::attribute association_user_id_node; + attribute_store::attribute association_credential_slot_node; +}; +association_nodes_t + helper_setup_association(attribute_store::attribute credential_slot_node, + user_credential_user_unique_id_t destination_user_id, + user_credential_slot_t destination_credential_slot) +{ + association_nodes_t association_nodes; + + association_nodes.association_user_id_node + = credential_slot_node.emplace_node( + ATTRIBUTE(ASSOCIATION_DESTINATION_USER_ID), + destination_user_id, + DESIRED_ATTRIBUTE); + + association_nodes.association_credential_slot_node + = credential_slot_node.emplace_node( + ATTRIBUTE(ASSOCIATION_DESTINATION_CREDENTIAL_SLOT), + destination_credential_slot, + DESIRED_ATTRIBUTE); + + return association_nodes; +} + +void helper_fill_credential_data( + attribute_store::attribute credential_slot_node, + std::string credential_data, + user_credential_modifier_type_t modifier_type) +{ + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA), + credential_data); + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE), + modifier_type); +} + +void helper_test_credential_data( + attribute_store::attribute credential_slot_node, + std::string credential_data, + user_credential_modifier_type_t modifier_type) +{ + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_DATA), + credential_data, + credential_slot_node); + + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE), + modifier_type, + credential_slot_node); +} + +void helper_simulate_credential_report_frame( + uint8_t credential_report_type, + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + uint8_t crb, + std::vector credential_data, + user_credential_modifier_type_t credential_modifier_type, + user_credential_modifier_node_id_t credential_modifier_node_id, + user_credential_type_t next_credential_type, + user_credential_slot_t next_credential_slot, + sl_status_t expected_status = SL_STATUS_OK) +{ + zwave_frame report_frame; + report_frame.add(credential_report_type); + report_frame.add(user_id); + report_frame.add(credential_type); + report_frame.add(credential_slot); + report_frame.add(static_cast(crb << 7)); + report_frame.add(credential_data); + report_frame.add(credential_modifier_type); + report_frame.add(credential_modifier_node_id); + report_frame.add(next_credential_type); + report_frame.add(next_credential_slot); + + helper_test_report_frame(CREDENTIAL_REPORT, report_frame, expected_status); +}; + +std::vector string_to_uint8_vector(const std::string &str) +{ + return std::vector(str.begin(), str.end()); +} + +void helper_create_credential_checksum_structure() +{ + // Since credential are attached to an user we simulate somes users + std::vector user_ids = {12, 15, 18}; + std::map + user_id_nodes = {}; + + for (auto user_id: user_ids) { + user_id_nodes.insert( + {user_id, + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id)}); + } + + // Create simulated envrionment for credentials + helper_simulate_credential_capabilites_report(1, + 1, + 1, + {ZCL_CRED_TYPE_PIN_CODE, + ZCL_CRED_TYPE_PASSWORD, + ZCL_CRED_TYPE_EYE_BIOMETRIC}, + {1, 1, 1}, + {8, 8, 8}, + {2, 34, 5}, + {6, 6, 10}, + {20, 20, 2}, + {1, 1, 95}); + + std::vector credential_user_ids + = {user_ids[0], user_ids[1], user_ids[0], user_ids[2]}; + + std::vector credential_types + = {ZCL_CRED_TYPE_PIN_CODE, + ZCL_CRED_TYPE_PIN_CODE, + ZCL_CRED_TYPE_PASSWORD, + ZCL_CRED_TYPE_EYE_BIOMETRIC}; + std::vector credential_slots = {2, 4, 1, 8}; + + std:: + vector> + credential_data = { + {0x39, 0x32, 0x37, 0x37}, // "9277" in ASCII + {0x39, 0x35, 0x34, 0x39, 0x38, 0x38}, // "954988" in ASCII + { + 0x00, 0x7A, 0x00, 0x77, 0x00, 0x61, 0x00, 0x76, 0x00, + 0x65, 0x00, 0x6E, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, + 0x00, 0x70, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, + 0x77, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x64}, // zwavenodepassword in Unicode UTF-16 format, in big endian order, + {0x24, 0x01} // Raw data + }; + + if (credential_types.size() != credential_slots.size() + || credential_slots.size() != credential_data.size() + || credential_slots.size() != credential_user_ids.size()) { + TEST_FAIL_MESSAGE("All vectors should be the same size"); + } + + for (size_t i = 0; i < credential_types.size(); i++) { + helper_simulate_credential_report_frame(0x00, // Credential Add + credential_user_ids[i], + credential_types[i], + credential_slots[i], + 0, + credential_data[i], + 0x02, // Anything but 0 + 0, + 0, + 0); + } +} + +///////////////////////////////////////////////////// +// Test case +///////////////////////////////////////////////////// + +/// Setup the test suite (called once before all test_xxx functions are called) +void suiteSetUp() +{ + datastore_init(":memory:"); + attribute_store_init(); + zpc_attribute_store_register_known_attribute_types(); +} + +/// Teardown the test suite (called once after all test_xxx functions are called) +int suiteTearDown(int num_failures) +{ + attribute_store_teardown(); + datastore_teardown(); + return num_failures; +} + +/// Called before each and every test +void setUp() +{ + zwave_setUp(command_class_handler, + &zwave_command_class_user_credential_init, + attributes_binding); +} + +/// Called after each and every test +void tearDown() {} + +//////////////////////////////////////////////////////////////////////////// +// User Capabilities Get/Report +//////////////////////////////////////////////////////////////////////////// +void test_user_credential_user_capabilities_get_happy_case() +{ + helper_test_get_set_frame_happy_case(USER_CAPABILITIES_GET); +} + +void test_user_credential_user_capabilities_report_happy_case() +{ + uint16_t number_of_users; + user_credential_supported_credential_rules_t cred_rule_bitmask; + uint8_t username_max_length; + uint8_t support_user_schedule; + uint8_t support_all_users_checksum; + uint8_t support_user_checksum; + uint8_t supported_user_types_bitmask_length; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask; + + // Test reported values based on the variables in this function + auto test_reported_values = [&]() { + // Create frame object + helper_simulate_user_capabilites_report(number_of_users, + cred_rule_bitmask, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + helper_test_attribute_value(ATTRIBUTE(NUMBER_OF_USERS), number_of_users); + helper_test_attribute_value(ATTRIBUTE(SUPPORTED_CREDENTIAL_RULES), + cred_rule_bitmask); + helper_test_attribute_value(ATTRIBUTE(MAX_USERNAME_LENGTH), + username_max_length); + helper_test_attribute_value(ATTRIBUTE(SUPPORT_USER_SCHEDULE), + support_user_schedule); + helper_test_attribute_value(ATTRIBUTE(SUPPORT_ALL_USERS_CHECKSUM), + support_all_users_checksum); + helper_test_attribute_value(ATTRIBUTE(SUPPORT_USER_CHECKSUM), + support_user_checksum); + helper_test_attribute_value(ATTRIBUTE(SUPPORTED_USER_TYPES), + supported_user_types_bitmask); + + attribute_store_node_t all_user_checksum_node + = cpp_endpoint_id_node.child_by_type(ATTRIBUTE(ALL_USERS_CHECKSUM)); + TEST_ASSERT_EQUAL_MESSAGE(ATTRIBUTE_STORE_INVALID_NODE, + all_user_checksum_node, + "ALL_USERS_CHECKSUM node should NOT exists yet " + "even if support_all_users_checksum == true"); + }; + + printf("Test with first set of data\n"); + number_of_users = 1212; + cred_rule_bitmask = 0b00000111; + username_max_length = 12; + support_user_schedule = 1; + support_all_users_checksum = 1; + support_user_checksum = 1; + supported_user_types_bitmask_length = 2; + supported_user_types_bitmask = 0b111111111; + // Do the testing + test_reported_values(); + + printf("Test with second set of data\n"); + number_of_users = 1313; + cred_rule_bitmask = 0b00011111; + username_max_length = 21; + support_user_schedule = 0; + support_all_users_checksum = 0; + support_user_checksum = 0; + supported_user_types_bitmask_length = 4; + supported_user_types_bitmask = 0xFFFFFFFF; + // Do the testing + test_reported_values(); +} + +//////////////////////////////////////////////////////////////////////////// +// Credential Capabilities Get/Report +//////////////////////////////////////////////////////////////////////////// +void test_user_credential_credential_capabilities_get_happy_case() +{ + helper_test_get_set_frame_happy_case(CREDENTIAL_CAPABILITIES_GET); +} + +void test_user_credential_credential_capabilities_report_happy_case() +{ + uint8_t credential_checksum_support = 1; + uint8_t admin_code_support = 1; + uint8_t admin_code_deactivation_support = 1; + std::vector credential_type = {1, 3, 4, 5}; + std::vector cl_support = {1, 0, 0, 1}; + std::vector supported_credential_slots = {1233, 11233, 21233, 33}; + std::vector min_length = {2, 23, 255, 12}; + std::vector max_length = {56, 156, 255, 32}; + std::vector cl_timeout = {100, 0, 0, 128}; + std::vector cl_steps = {2, 0, 0, 12}; + uint16_t expected_credential_type_mask = 0b11101; + + auto test_report_values = [&]() { + helper_test_attribute_value(ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM), + credential_checksum_support); + helper_test_attribute_value(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE), + admin_code_support); + helper_test_attribute_value(ATTRIBUTE(SUPPORT_ADMIN_PIN_CODE_DEACTIVATION), + admin_code_deactivation_support); + auto admin_code_node + = cpp_endpoint_id_node.child_by_type(ATTRIBUTE(ADMIN_PIN_CODE)); + if (admin_code_support == 1) { + TEST_ASSERT_TRUE_MESSAGE(admin_code_node.is_valid(), + "Admin code node should exists"); + // For next tests + admin_code_node.delete_node(); + } else { + TEST_ASSERT_FALSE_MESSAGE(admin_code_node.is_valid(), + "Admin code node should NOT exists"); + } + + helper_test_attribute_value( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES, + expected_credential_type_mask); + + for (uint8_t i = 0; i < credential_type.size(); i++) { + printf("Testing credential batch %d\n", i); + + auto type_node = cpp_endpoint_id_node.child_by_type( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + i); + TEST_ASSERT_NOT_EQUAL_MESSAGE(ATTRIBUTE_STORE_INVALID_NODE, + type_node, + "Credential type node should be defined"); + TEST_ASSERT_EQUAL_MESSAGE(credential_type[i], + type_node.reported(), + "Incorrect credential type"); + + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MIN_LENGTH), + min_length[i], + type_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MAX_LENGTH), + max_length[i], + type_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_LEARN_SUPPORT), + cl_support[i], + type_node); + helper_test_attribute_value( + ATTRIBUTE(CREDENTIAL_LEARN_RECOMMENDED_TIMEOUT), + cl_timeout[i], + type_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_LEARN_NUMBER_OF_STEPS), + cl_steps[i], + type_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_SUPPORTED_SLOT_COUNT), + supported_credential_slots[i], + type_node); + } + }; + + printf("Test with first set of data\n"); + helper_simulate_credential_capabilites_report(credential_checksum_support, + admin_code_support, + admin_code_deactivation_support, + credential_type, + cl_support, + supported_credential_slots, + min_length, + max_length, + cl_timeout, + cl_steps); + + test_report_values(); + + printf("Test with second set of data\n"); + credential_checksum_support = 0; + admin_code_support = 0; + admin_code_deactivation_support = 0; + credential_type = {6, 7, 8}; + cl_support = {0, 1, 1}; + supported_credential_slots = {15, 1565, 153}; + min_length = {155, 15, 5}; + max_length = {180, 111, 11}; + cl_timeout = {0, 10, 12}; + cl_steps = {0, 1, 2}; + expected_credential_type_mask = 0b11100000; + + helper_simulate_credential_capabilites_report(credential_checksum_support, + admin_code_support, + admin_code_deactivation_support, + credential_type, + cl_support, + supported_credential_slots, + min_length, + max_length, + cl_timeout, + cl_steps); + + test_report_values(); +} + +//////////////////////////////////////////////////////////////////////////// +// User Set/Get/Report +//////////////////////////////////////////////////////////////////////////// +void test_user_credential_user_set_add_or_modify_happy_case() +{ + user_credential_user_unique_id_t user_id = 12121; + user_credential_operation_type_t operation_type = USER_SET_OPERATION_TYPE_ADD; + user_credential_type_t user_type = 5; + user_credential_rule_t credential_rule = 2; + user_credential_user_active_state_t user_active_state = 1; + user_credential_expiring_timeout_minutes_t expiring_timeout = 55; + user_credential_user_name_encoding_t user_name_encoding = 0; + std::string user_name = "DoUzE"; + + // Create structure + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + auto operation_type_node + = user_id_node.emplace_node(ATTRIBUTE(USER_OPERATION_TYPE), + operation_type, + DESIRED_ATTRIBUTE); + user_id_node.emplace_node(ATTRIBUTE(USER_TYPE), user_type, DESIRED_ATTRIBUTE); + user_id_node.emplace_node(ATTRIBUTE(USER_ACTIVE_STATE), user_active_state); + user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_RULE), + credential_rule, + DESIRED_ATTRIBUTE); + user_id_node.emplace_node(ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES), + expiring_timeout); + user_id_node.emplace_node(ATTRIBUTE(USER_NAME_ENCODING), + user_name_encoding, + DESIRED_ATTRIBUTE); + user_id_node.emplace_node(ATTRIBUTE(USER_NAME), user_name); + + auto create_and_send_set_frame = [&]() { + zwave_frame set_frame; + set_frame.add(operation_type); + set_frame.add(user_id); + set_frame.add(user_type); + set_frame.add(user_active_state); + set_frame.add(credential_rule); + set_frame.add(expiring_timeout); + set_frame.add(user_name_encoding); + set_frame.add(user_name); + + helper_test_get_set_frame_happy_case(USER_SET, + operation_type_node, + set_frame); + }; + + // Test user set + printf("Send with USER_SET_OPERATION_TYPE_ADD\n"); + create_and_send_set_frame(); + + printf("Send with USER_SET_OPERATION_TYPE_MODIFY\n"); + operation_type = USER_SET_OPERATION_TYPE_MODIFY; + operation_type_node.set_desired(operation_type); + create_and_send_set_frame(); +} + +void test_user_credential_user_delete_happy_case() +{ + user_credential_user_unique_id_t user_id = 12121; + user_credential_operation_type_t operation_type + = USER_SET_OPERATION_TYPE_DELETE; + + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + auto operation_type_node + = user_id_node.emplace_node(ATTRIBUTE(USER_OPERATION_TYPE), + operation_type, + DESIRED_ATTRIBUTE); + + zwave_frame set_frame; + set_frame.add(operation_type); + set_frame.add(user_id); + + helper_test_get_set_frame_happy_case(USER_SET, + operation_type_node, + set_frame); +} + +void test_user_credential_user_set_invalid_node() +{ + helper_test_get_set_fail_case(USER_GET, SL_STATUS_NOT_SUPPORTED); +} + +void test_user_credential_user_get_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + DESIRED_ATTRIBUTE); + + zwave_frame get_frame; + get_frame.add(user_id); + + helper_test_get_set_frame_happy_case(USER_GET, user_id_node, get_frame); +} + +void test_user_credential_user_get_not_found() +{ + helper_test_get_set_fail_case(USER_GET, SL_STATUS_NOT_SUPPORTED); +} + +void helper_simulate_user_report_frame( + uint8_t user_report_type, + user_credential_user_unique_id_t next_user_id, + user_credential_modifier_type_t user_modifier_type, + user_credential_modifier_node_id_t user_modifier_node_id, + user_credential_user_unique_id_t user_id, + user_credential_user_type_t user_type, + user_credential_user_active_state_t user_active_state, + user_credential_supported_credential_rules_t credential_rule, + user_credential_expiring_timeout_minutes_t expiring_timeout_minutes, + user_credential_user_name_encoding_t user_name_encoding, + const std::string &user_name, + sl_status_t expected_status = SL_STATUS_OK) +{ + zwave_frame report_frame; + report_frame.add(user_report_type); + report_frame.add(next_user_id); + report_frame.add(user_modifier_type); + report_frame.add(user_modifier_node_id); + report_frame.add(user_id); + report_frame.add(user_type); + report_frame.add(user_active_state); + report_frame.add(credential_rule); + report_frame.add(expiring_timeout_minutes); + report_frame.add(user_name_encoding); + report_frame.add(user_name); + + // Use helper function to get the report frame + helper_test_report_frame(USER_REPORT, report_frame, expected_status); +} + +// FIXME: Will be changed +// https://github.com/Z-Wave-Alliance/AWG/issues/168 +std::vector helper_create_credential_notification_report( + user_credential_user_unique_id_t user_id, + user_credential_type_t credential_type, + user_credential_slot_t credential_slot, + bool crb, + const std::string &credential_data, + user_credential_modifier_type_t modifier_type, + user_credential_modifier_node_id_t modifier_node_id) +{ + zwave_frame report_frame; + + report_frame.add(user_id); + report_frame.add(credential_type); + report_frame.add(credential_slot); + report_frame.add(static_cast(crb ? 1 : 0)); + report_frame.add(credential_data); + report_frame.add(modifier_type); + report_frame.add(modifier_node_id); + + return report_frame; +}; + +void test_user_credential_user_report_happy_case() +{ + constexpr user_credential_user_unique_id_t EXPECTED_FIRST_USER_ID = 12; + constexpr user_credential_user_unique_id_t EXPECTED_SECOND_USER_ID = 1212; + + user_credential_user_unique_id_t next_user_id = EXPECTED_SECOND_USER_ID; + user_credential_modifier_type_t user_modifier_type = 2; + user_credential_modifier_node_id_t user_modifier_node_id = 1313; + user_credential_user_unique_id_t user_id = EXPECTED_FIRST_USER_ID; + user_credential_user_type_t user_type = 3; + user_credential_user_active_state_t user_active_state = 1; + user_credential_supported_credential_rules_t credential_rule = 2; + user_credential_expiring_timeout_minutes_t expiring_timeout_minutes = 1515; + user_credential_user_name_encoding_t user_name_encoding = 0; + std::string user_name = "DoUzE"; + + // Those functions are exposed and checks user values, so we need to setup the capabilities + uint16_t number_of_users = 1312; + user_credential_supported_credential_rules_t cred_rule_bitmask = 0x0F; + uint8_t username_max_length = 112; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum + = 1; // Used to check if the user checksum will be computed at the end + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 2; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 0xFF; + helper_simulate_user_capabilites_report(number_of_users, + cred_rule_bitmask, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + auto test_user_values = [&](const attribute_store::attribute &user_node) { + TEST_ASSERT_EQUAL_MESSAGE( + user_id, + user_node.reported(), + "User Unique ID is incorrect"); + + helper_test_attribute_value(ATTRIBUTE(USER_MODIFIER_TYPE), + user_modifier_type, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_TYPE), user_type, user_node); + helper_test_attribute_value(ATTRIBUTE(USER_ACTIVE_STATE), + user_active_state, + user_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_RULE), + credential_rule, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES), + expiring_timeout_minutes, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_NAME_ENCODING), + user_name_encoding, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_NAME), user_name, user_node); + helper_test_attribute_value(ATTRIBUTE(USER_MODIFIER_NODE_ID), + user_modifier_node_id, + user_node); + + // Check user credential desired values + auto credential_type_node + = helper_test_and_get_node(ATTRIBUTE(CREDENTIAL_TYPE), user_node); + + auto credential_type + = credential_type_node.reported(); + auto credential_slot = helper_test_and_get_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_type_node) + .desired(); + + TEST_ASSERT_EQUAL_MESSAGE( + 0, + credential_type, + "Credential Type should be at 0 and should exists"); + TEST_ASSERT_EQUAL_MESSAGE( + 0, + credential_slot, + "Credential Slot should be at 0 and should exists"); + }; // end test_user_values lambda + + printf("First user creation\n"); + + // Create first user + auto first_user_id_node + = cpp_endpoint_id_node.add_node(ATTRIBUTE(USER_UNIQUE_ID)); + first_user_id_node.set_desired(0); + + zwave_frame get_frame; + get_frame.add(static_cast(0)); + helper_test_get_set_frame_happy_case(USER_GET, first_user_id_node, get_frame); + + // Call report + helper_simulate_user_report_frame(0x04, + next_user_id, + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout_minutes, + user_name_encoding, + user_name); + + // Test values + // For the first + first_user_id_node + = cpp_endpoint_id_node.child_by_type(ATTRIBUTE(USER_UNIQUE_ID), 1); + test_user_values(first_user_id_node); + + // Test structure + auto user_id_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + TEST_ASSERT_EQUAL_MESSAGE(2, + user_id_count, + "User node count mismatch. Should be 2 by now. One " + "with special id 0 and the " + "reported one"); + + // Simulate no credential for this User + helper_simulate_credential_report_frame(0x00, + user_id, + 0, + 0, + 0, + std::vector(), + 0, + 0, + 0, + 0); + auto second_user_id_node + = cpp_endpoint_id_node.child_by_type(ATTRIBUTE(USER_UNIQUE_ID), 2); + + TEST_ASSERT_TRUE_MESSAGE( + second_user_id_node.is_valid(), + "Second user node should be created & valid"); + + TEST_ASSERT_FALSE_MESSAGE( + cpp_endpoint_id_node.child_by_type(ATTRIBUTE(ALL_USERS_CHECKSUM)) + .is_valid(), + "ALL_USERS_CHECKSUM node should not be created yet"); + + user_id_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + TEST_ASSERT_EQUAL_MESSAGE( + 3, + user_id_count, + "User node count mismatch. Should be 3 by now. One " + "with special id 0, the reported one & the next in queue"); + + printf("Second and last user creation\n"); + + TEST_ASSERT_EQUAL_MESSAGE( + next_user_id, + second_user_id_node.desired(), + "Second user id should have it's desired value defined"); + + // Simulate a GET on that user + // Removes the desired state and sets to reported instead + get_frame.clear(); + get_frame.add(next_user_id); + helper_test_get_set_frame_happy_case(USER_GET, + second_user_id_node, + get_frame); + + // Second and last user + next_user_id = 0; + user_modifier_type = 3; + user_modifier_node_id = 1414; + user_id = EXPECTED_SECOND_USER_ID; + user_type = 5; + user_active_state = 0; + credential_rule = 1; + user_name_encoding = 1; + user_name = "NoDoUzE4YoU"; + + helper_simulate_user_report_frame(0x04, + next_user_id, + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout_minutes, + user_name_encoding, + user_name); + // Test values + test_user_values(second_user_id_node); + + // Test structure + // The report function should not have created an other user unique id node (next_user_id = 0) + user_id_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + + TEST_ASSERT_EQUAL_MESSAGE( + 3, + user_id_count, + "User node count mismatch. Should only 2 users + 1 with id 0 created."); + + TEST_ASSERT_EQUAL_MESSAGE( + EXPECTED_FIRST_USER_ID, + first_user_id_node.reported(), + "First user id mismatch"); + TEST_ASSERT_EQUAL_MESSAGE( + EXPECTED_SECOND_USER_ID, + second_user_id_node.reported(), + "Second user id mismatch"); + + // Still no credential, so we can create the all user checksum + helper_simulate_credential_report_frame(0x00, + user_id, + 0, + 0, + 0, + std::vector(), + 0, + 0, + 0, + 0); + TEST_ASSERT_TRUE_MESSAGE( + cpp_endpoint_id_node.child_by_type(ATTRIBUTE(ALL_USERS_CHECKSUM)) + .is_valid(), + "ALL_USERS_CHECKSUM node should be created"); +} + +void test_user_credential_no_all_users_checksum() +{ + user_credential_user_unique_id_t next_user_id = 0; + user_credential_modifier_type_t user_modifier_type = 2; + user_credential_modifier_node_id_t user_modifier_node_id = 1313; + user_credential_user_unique_id_t user_id = 12; + user_credential_user_type_t user_type = 3; + user_credential_user_active_state_t user_active_state = 1; + user_credential_supported_credential_rules_t credential_rule = 2; + user_credential_expiring_timeout_minutes_t expiring_timeout_minutes = 1515; + user_credential_user_name_encoding_t user_name_encoding = 0; + std::string user_name = "DoUzE"; + + // Those functions are exposed and checks user values, so we need to setup the capabilities + uint16_t number_of_users = 1312; + user_credential_supported_credential_rules_t cred_rule_bitmask = 0x0F; + uint8_t username_max_length = 112; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum + = 0; // Used to check if the user checksum will be computed at the end + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 2; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 0xFF; + helper_simulate_user_capabilites_report(number_of_users, + cred_rule_bitmask, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + // Create first user + auto first_user_id_node + = cpp_endpoint_id_node.add_node(ATTRIBUTE(USER_UNIQUE_ID)); + first_user_id_node.set_desired(0); + + zwave_frame get_frame; + get_frame.add(static_cast(0)); + helper_test_get_set_frame_happy_case(USER_GET, first_user_id_node, get_frame); + + // Call report + helper_simulate_user_report_frame(0x04, + next_user_id, + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout_minutes, + user_name_encoding, + user_name); + + TEST_ASSERT_FALSE_MESSAGE( + cpp_endpoint_id_node.child_by_type(ATTRIBUTE(ALL_USERS_CHECKSUM)) + .is_valid(), + "ALL_USERS_CHECKSUM node should not be created yet"); +} +void test_user_credential_user_report_user_with_id0() +{ + // User Report should have returned SL_STATUS_OK and ignore the frame + helper_simulate_user_report_frame(0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, "DOUZE"); + + // Check that no user_unique_id node has been created (and the invalid node was deleted) + auto user_id_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + + TEST_ASSERT_EQUAL_MESSAGE(0, + user_id_count, + "No user_unique_id node should be created"); +} + +void test_user_credential_user_report_user_deleted() +{ + // Create user id with reported ID of 0 to simulate user get of id 0 + user_credential_user_unique_id_t user_id = 12; + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + DESIRED_ATTRIBUTE); + + auto user_id_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + TEST_ASSERT_EQUAL_MESSAGE(1, user_id_count, "Should have one user by now"); + + // Should delete this user + helper_simulate_user_report_frame(0x04, + user_id, + USER_REPORT_DNE, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + "????"); + + user_id_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + TEST_ASSERT_EQUAL_MESSAGE(1, + user_id_count, + "Should not have any user by now"); +} + +//////////////////////////////////////////////////////////////////////////// +// Credential Set/Get/Report +//////////////////////////////////////////////////////////////////////////// + +void helper_test_credential_set( + user_credential_operation_type_t operation_type, + std::vector credential_data, + attribute_store_node_value_state_t credential_data_state) +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = 2; + user_credential_slot_t credential_slot = 1212; + + // Create the node with reported attribute + auto nodes = helper_create_credential_structure(user_id, + credential_type, + credential_slot, + REPORTED_ATTRIBUTE); + auto credential_slot_node = nodes.credential_slot_node; + + // Operation type + auto operation_type_node + = credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_OPERATION_TYPE), + operation_type, + DESIRED_ATTRIBUTE); + // CREDENTIAL_DATA + credential_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA), + credential_data, + credential_data_state); + + zwave_frame set_frame; + set_frame.add(user_id); + set_frame.add(credential_type); + set_frame.add(credential_slot); + set_frame.add(operation_type); + if (credential_data.size() > 0) { + set_frame.add(credential_data); + } else { + set_frame.add(static_cast(0x00)); + } + + helper_test_get_set_frame_happy_case(CREDENTIAL_SET, + operation_type_node, + set_frame); +} + +//>> Set +void test_user_credential_credential_set_1byte_happy_case() +{ + helper_test_credential_set(USER_CREDENTIAL_OPERATION_TYPE_ADD, + {12}, + REPORTED_ATTRIBUTE); +} + +void test_user_credential_credential_set_12byte_happy_case() +{ + helper_test_credential_set(USER_CREDENTIAL_OPERATION_TYPE_ADD, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}, + DESIRED_ATTRIBUTE); +} + +void test_user_credential_credential_set_invalid_node() +{ + helper_test_get_set_fail_case(CREDENTIAL_SET); +} + +void test_user_credential_credential_set_delete_happy_case() +{ + helper_test_credential_set(USER_CREDENTIAL_OPERATION_TYPE_DELETE, + {}, // Empty credential data + DESIRED_ATTRIBUTE // doesn't matter here + ); +} + +//>> Get +void test_user_credential_credential_get_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = 2; + user_credential_slot_t credential_slot = 1212; + + auto nodes = helper_create_credential_structure(user_id, + credential_type, + credential_slot); + + zwave_frame get_frame; + get_frame.add(user_id); + get_frame.add(credential_type); + get_frame.add(credential_slot); + + helper_test_get_set_frame_happy_case(CREDENTIAL_GET, + nodes.credential_slot_node, + get_frame); +} + +void test_user_credential_credential_get_no_credential_type() +{ + helper_test_get_set_fail_case(CREDENTIAL_GET, SL_STATUS_NOT_SUPPORTED); +} + +void test_user_credential_credential_report_no_credential() +{ + user_credential_user_unique_id_t user_id = 12; + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Should return ok since credential_type and credential node is 0 + helper_simulate_credential_report_frame(0x04, // Credential get, + user_id, + 0, + 0, + 0, + {}, + 0, + 0, + 0, + 0); +} + +void test_user_credential_credential_report_missing_user() +{ + // Not found since we haven't created any user_unique_id + helper_simulate_credential_report_frame(0x04, + 12, + 1, + 1, + 0, + {}, + 0, + 0, + 0, + 0, + SL_STATUS_FAIL); +} + +void test_user_credential_credential_report_happy_case() +{ + user_credential_user_unique_id_t user_id = 122; + user_credential_type_t credential_type = 12; + user_credential_slot_t credential_slot = 1212; + uint8_t crb = 1; + std::vector credential_data = {12, 13, 14, 15, 16}; + user_credential_modifier_type_t credential_modifier_type = 13; + user_credential_modifier_node_id_t credential_modifier_node_id = 1312; + user_credential_type_t next_credential_type = 12; + user_credential_slot_t next_credential_slot = 1; + + auto test_credential_values + = [&](const attribute_store::attribute &credential_type_node, + const attribute_store::attribute &credential_slot_node) { + // Check main node value + TEST_ASSERT_EQUAL_MESSAGE( + credential_type, + credential_type_node.reported(), + "Credential type value mismatch"); + TEST_ASSERT_EQUAL_MESSAGE( + credential_slot, + credential_slot_node.reported(), + "Credential slot value mismatch"); + + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_READ_BACK), + crb, + credential_slot_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE), + credential_modifier_type, + credential_slot_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MODIFIER_NODE_ID), + credential_modifier_node_id, + credential_slot_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_DATA), + credential_data, + credential_slot_node); + }; // end test_credential_values lambda + + auto check_credentials_node_count + = [](const attribute_store::attribute &user_id_node, + size_t expected_credential_type_count, + size_t expected_credential_slot_count) { + auto count_credential_type + = user_id_node.children(ATTRIBUTE(CREDENTIAL_TYPE)).size(); + TEST_ASSERT_EQUAL_MESSAGE(expected_credential_type_count, + count_credential_type, + "Incorrect credential type count"); + + size_t count_credential_slot = 0; + for (size_t i = 0; i < count_credential_type; i++) { + auto credential_type_node + = user_id_node.child_by_type(ATTRIBUTE(CREDENTIAL_TYPE), i); + count_credential_slot + += credential_type_node.children(ATTRIBUTE(CREDENTIAL_SLOT)).size(); + } + + TEST_ASSERT_EQUAL_MESSAGE(expected_credential_slot_count, + count_credential_slot, + "Incorrect credential slot count"); + }; + + auto check_next_credential_node_value + = [&](const attribute_store::attribute &next_credential_type_node, + const attribute_store::attribute &next_credential_slot_node) { + // First check node existence + TEST_ASSERT_TRUE_MESSAGE(next_credential_type_node.is_valid(), + "next_credential_type_node should exist"); + TEST_ASSERT_TRUE_MESSAGE(next_credential_slot_node.is_valid(), + "next_credential_slot_node should exist"); + + TEST_ASSERT_EQUAL_MESSAGE( + next_credential_type, + next_credential_type_node.reported(), + "Next Credential Type value mismatch"); + TEST_ASSERT_EQUAL_MESSAGE( + next_credential_slot, + next_credential_slot_node.desired(), + "Next Credential Slot value mismatch"); + }; + + //>>>> First credential + printf("First credential creation\n"); + + // Create first credential + auto nodes + = helper_create_credential_structure(user_id, 0, 0, DESIRED_ATTRIBUTE); + + auto user_id_node = nodes.user_id_node; + auto first_credential_type_node = nodes.credential_type_node; + auto first_credential_slot_node = nodes.credential_slot_node; + + attribute_store_log(); + + zwave_frame get_frame; + get_frame.add(user_id); + get_frame.add(static_cast(0)); + get_frame.add(static_cast(0)); + + // Simulate get on that credential + helper_test_get_set_frame_happy_case(CREDENTIAL_GET, + first_credential_slot_node, + get_frame); + + // Call report + helper_simulate_credential_report_frame(0x04, // Response to get + user_id, + credential_type, + credential_slot, + crb, + credential_data, + credential_modifier_type, + credential_modifier_node_id, + next_credential_type, + next_credential_slot); + + // Test values + test_credential_values(first_credential_type_node, + first_credential_slot_node); + // We should have 1 credential type and 2 credential slot + check_credentials_node_count(user_id_node, 1, 2); + + // Test if next credentials are well defined + auto second_credential_slot_node + = first_credential_type_node.child_by_type(ATTRIBUTE(CREDENTIAL_SLOT), 1); + check_next_credential_node_value(first_credential_type_node, + second_credential_slot_node); + + //>>>> Second credential + printf("Second credential creation\n"); + + credential_type = next_credential_type; + credential_slot = next_credential_slot; + crb = 0; + credential_data = {1, 2}; + credential_modifier_type = 3; + credential_modifier_node_id = 13121; + next_credential_type = 121; + next_credential_slot = 3; + + // Simulate get on that credential + get_frame.clear(); + get_frame.add(user_id); + get_frame.add(credential_type); + get_frame.add(credential_slot); + helper_test_get_set_frame_happy_case(CREDENTIAL_GET, + second_credential_slot_node, + get_frame); + + // Call report + helper_simulate_credential_report_frame(0x04, // Response to get + user_id, + credential_type, + credential_slot, + crb, + credential_data, + credential_modifier_type, + credential_modifier_node_id, + next_credential_type, + next_credential_slot); + + // Test values + test_credential_values(first_credential_type_node, + second_credential_slot_node); + // We should have 2 credential type and 2 credential slot + check_credentials_node_count(user_id_node, 2, 3); + + auto second_credential_type_node + = user_id_node.child_by_type(ATTRIBUTE(CREDENTIAL_TYPE), 1); + auto third_credential_slot_node + = second_credential_type_node.child_by_type(ATTRIBUTE(CREDENTIAL_SLOT), 0); + + // New nodes so we check their desired values + check_next_credential_node_value(second_credential_type_node, + third_credential_slot_node); + + //>>>> Third credential + printf("Third and last credential creation\n"); + credential_type = next_credential_type; + credential_slot = next_credential_slot; + crb = 1; + credential_data = {15}; + credential_modifier_type = 2; + credential_modifier_node_id = 12; + next_credential_type = 0; + next_credential_slot = 0; + + // Simulate get on that credential + get_frame.clear(); + get_frame.add(user_id); + get_frame.add(credential_type); + get_frame.add(credential_slot); + helper_test_get_set_frame_happy_case(CREDENTIAL_GET, + third_credential_slot_node, + get_frame); + + // Call report + helper_simulate_credential_report_frame(0x04, // Response to get + user_id, + credential_type, + credential_slot, + crb, + credential_data, + credential_modifier_type, + credential_modifier_node_id, + next_credential_type, + next_credential_slot); + + // Test values + test_credential_values(second_credential_type_node, + third_credential_slot_node); + // We should still have 2 credential type and 3 credential slots since it was the last credential + check_credentials_node_count(user_id_node, 2, 3); +} + +//////////////////////////////////////////////////////////////////////////// +// Attribute creation +//////////////////////////////////////////////////////////////////////////// +void test_attribute_creation_happy_case() +{ + helper_set_version(1); + + std::vector created_types = { + ATTRIBUTE(NUMBER_OF_USERS), + ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM), + }; + + for (auto &type: created_types) { + const std::string error_msg + = "Attribute " + std::string(attribute_store_get_type_name(type)) + + " should exist"; + + TEST_ASSERT_NOT_EQUAL_MESSAGE( + ATTRIBUTE_STORE_INVALID_NODE, + attribute_store_get_node_child_by_type(endpoint_id_node, type, 0), + error_msg.c_str()); + } +} + +void test_attribute_creation_no_version() +{ + helper_set_version(0); + + std::vector created_types = { + ATTRIBUTE(NUMBER_OF_USERS), + ATTRIBUTE(SUPPORT_CREDENTIAL_CHECKSUM), + }; + + for (auto &type: created_types) { + const std::string error_msg + = "Attribute " + std::string(attribute_store_get_type_name(type)) + + " should NOT exist"; + + TEST_ASSERT_EQUAL_MESSAGE( + ATTRIBUTE_STORE_INVALID_NODE, + attribute_store_get_node_child_by_type(endpoint_id_node, type, 0), + error_msg.c_str()); + } +} + +void test_post_interview_discovery() +{ + zwave_network_management_get_node_id_IgnoreAndReturn(zpc_node_id); + zwave_network_management_get_home_id_IgnoreAndReturn(home_id); + + // Lambdas + auto count_user_node = [](size_t expected_value) { + auto user_id_node_count + = cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(); + TEST_ASSERT_EQUAL_MESSAGE(expected_value, + user_id_node_count, + "User ID node count mismatch"); + }; + + // Test logic + attribute_store::attribute cpp_node_id_node(node_id_node); + + NodeStateNetworkStatus network_status = ZCL_NODE_STATE_NETWORK_STATUS_OFFLINE; + auto network_status_node + = cpp_node_id_node.emplace_node(DOTDOT_ATTRIBUTE_ID_STATE_NETWORK_STATUS, + network_status); + + count_user_node(0); + + // Interview state + network_status = ZCL_NODE_STATE_NETWORK_STATUS_ONLINE_INTERVIEWING; + network_status_node.set_reported(network_status); + count_user_node(0); + + // Simulate one more endpoint and only add nif to one of them + + // Add NIF to our endpoint to tell that we support User Credential + std::vector nif_value = {COMMAND_CLASS_USER_CREDENTIAL}; + cpp_endpoint_id_node.emplace_node(ATTRIBUTE_ZWAVE_SECURE_NIF, nif_value); + + // Add another endpoint without User Credential support + zwave_endpoint_id_t endpoint_id_2 = endpoint_id + 12; + cpp_node_id_node.emplace_node(ATTRIBUTE_ENDPOINT_ID, endpoint_id_2); + + // Display current store log for debug purpose + attribute_store_log(); + + // Set the network status to online + network_status = ZCL_NODE_STATE_NETWORK_STATUS_ONLINE_FUNCTIONAL; + network_status_node.set_reported(network_status); + + // Now we check attribute store + auto user_id_node = helper_test_attribute_value( + ATTRIBUTE(USER_UNIQUE_ID), + static_cast(0), + cpp_endpoint_id_node, + DESIRED_ATTRIBUTE); + count_user_node(1); + + // Simulate user found + user_credential_user_unique_id_t user_id = 12; + user_id_node.set_reported(user_id); + + // Go back to Interview state + network_status = ZCL_NODE_STATE_NETWORK_STATUS_ONLINE_INTERVIEWING; + network_status_node.set_reported(network_status); + + // Then back in Online Functional + network_status = ZCL_NODE_STATE_NETWORK_STATUS_ONLINE_FUNCTIONAL; + network_status_node.set_reported(network_status); + + // User should still be there + count_user_node(1); + // With right value + helper_test_attribute_value(ATTRIBUTE(USER_UNIQUE_ID), user_id); +} + +void test_user_credential_add_credential_already_defined_cred_type_and_slot() +{ + // Initialize the notification callback + helper_set_version(1); + + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + std::string credential_data = "12"; + bool crb = true; + user_credential_modifier_type_t credential_modifier_type = 2; + user_credential_modifier_node_id_t credential_modifier_node_id = 1212; + + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE}; + std::vector supported_cl = {1}; + std::vector supported_credential_slots = {1}; + std::vector supported_cred_min_length = {2}; + std::vector supported_cred_max_length = {6}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1}, + {1}); + + // Add credential + sl_status_t status = zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + credential_data.c_str()); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Credential add should have returned SL_STATUS_OK"); + + helper_simulate_credential_report_frame( + 0x00, // Credential added + user_id, + credential_type, + credential_slot, + crb, + string_to_uint8_vector(credential_data), + credential_modifier_type, + credential_modifier_node_id, + 0, + 0); + + // Try to add same credential type and slot on same user but with different credential data + credential_data = "1234"; + status = zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + credential_data.c_str()); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + status, + "Credential add should have returned SL_STATUS_FAIL (trying to add same " + "credential type/slot to same user)."); + + // Try to add same credential type/slot on other user + user_id = 15; + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + status = zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + credential_data.c_str()); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + status, + "Credential add should have returned SL_STATUS_FAIL (trying to add same " + "credential type/slot to different user)."); +} + +void test_user_credential_add_credential_invalid_slot() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 58; + std::string credential_data = "12"; + + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Se capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE}; + std::vector supported_cl = {1}; + std::vector supported_credential_slots = {1}; + std::vector supported_cred_min_length = {2}; + std::vector supported_cred_max_length = {6}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1}, + {1}); + + // Add credential + sl_status_t status = zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + credential_data.c_str()); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + status, + "Credential add should have returned SL_STATUS_FAIL (trying to add a non " + "supported slot)"); +} + +void test_user_credential_user_add_modify_delete_happy_case() +{ + // Those functions are exposed and checks user values, so we need to setup the capabilities + uint16_t number_of_users = 12; + user_credential_supported_credential_rules_t cred_rule_bitmask = 0x0F; + uint8_t username_max_length = 112; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum = 0; + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 2; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 0xFF; + helper_simulate_user_capabilites_report(number_of_users, + cred_rule_bitmask, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + // Setup user + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t user_type = 2; + user_credential_rule_t credential_rule = 1; + user_credential_user_active_state_t user_active_state = 1; + user_credential_expiring_timeout_minutes_t expiring_timeout = 0; + user_credential_user_name_encoding_t user_name_encoding = 0; + std::string user_name = "MICHEL VNR"; + + // Add user + sl_status_t status + = zwave_command_class_user_credential_add_new_user(endpoint_id_node, + user_id, + user_type, + credential_rule, + user_active_state, + expiring_timeout, + user_name_encoding, + user_name.c_str()); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "zwave_command_class_user_credential_add_new_user " + "should have returned SL_STATUS_OK"); + // Get user node + auto user_node = helper_test_and_get_node(ATTRIBUTE(USER_UNIQUE_ID)); + auto operation_type_node + = helper_test_and_get_node(ATTRIBUTE(USER_OPERATION_TYPE), user_node); + TEST_ASSERT_EQUAL_MESSAGE( + USER_SET_OPERATION_TYPE_ADD, + operation_type_node.desired(), + "Operation type mismatch for user add"); + + zwave_frame set_frame; + set_frame.add( + static_cast(USER_SET_OPERATION_TYPE_ADD)); + set_frame.add(user_id); + set_frame.add(user_type); + set_frame.add(user_active_state); + set_frame.add(credential_rule); + set_frame.add(expiring_timeout); + set_frame.add(user_name_encoding); + set_frame.add(user_name); + helper_test_get_set_frame_happy_case(USER_SET, + operation_type_node, + set_frame); + + // Create notification report frame + user_credential_modifier_type_t user_modifier_type = 2; + user_credential_modifier_node_id_t user_modifier_node_id = 1212; + + helper_simulate_user_report_frame(USER_SET_OPERATION_TYPE_ADD, + 0, // Next user id + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout, + user_name_encoding, + user_name); + + // Check values + auto test_attribute_store_values = [&]() { + helper_test_attribute_value(ATTRIBUTE(USER_MODIFIER_TYPE), + user_modifier_type, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_TYPE), user_type, user_node); + helper_test_attribute_value(ATTRIBUTE(USER_ACTIVE_STATE), + user_active_state, + user_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_RULE), + credential_rule, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_MODIFIER_NODE_ID), + user_modifier_node_id, + user_node); + helper_test_attribute_value(ATTRIBUTE(USER_EXPIRING_TIMEOUT_MINUTES), + expiring_timeout, + user_node); + + helper_test_attribute_value(ATTRIBUTE(USER_NAME), user_name, user_node); + }; + test_attribute_store_values(); + + // Now let's modify this user + user_type = 7; + credential_rule = 2; + user_active_state = 0; + expiring_timeout = 10; + user_name_encoding = 2; + user_name = "JACKIE CAMION TURBO PLUS"; + + status = zwave_command_class_user_credential_modify_user(endpoint_id_node, + user_id, + user_type, + credential_rule, + user_active_state, + expiring_timeout, + user_name_encoding, + user_name.c_str()); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "zwave_command_class_user_credential_modify_user " + "should have returned SL_STATUS_OK"); + TEST_ASSERT_EQUAL_MESSAGE( + USER_SET_OPERATION_TYPE_MODIFY, + operation_type_node.desired(), + "Operation type mismatch for user modify"); + + // Set frame + set_frame.clear(); + set_frame.add(static_cast( + USER_SET_OPERATION_TYPE_MODIFY)); + set_frame.add(user_id); + set_frame.add(user_type); + set_frame.add(user_active_state); + set_frame.add(credential_rule); + set_frame.add(expiring_timeout); + set_frame.add(user_name_encoding); + set_frame.add(user_name); + helper_test_get_set_frame_happy_case(USER_SET, + operation_type_node, + set_frame); + + // Report back + helper_simulate_user_report_frame(USER_SET_OPERATION_TYPE_MODIFY, + 0, // Next user id + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout, + user_name_encoding, + user_name); + + // Create notification report frame + user_modifier_type = 5; + user_modifier_node_id = 12122; + + helper_simulate_user_report_frame(USER_SET_OPERATION_TYPE_MODIFY, + 0, // Next user id + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout, + user_name_encoding, + user_name); + + // Check values + test_attribute_store_values(); + + // Now let's delete this user + status = zwave_command_class_user_credential_delete_user(endpoint_id_node, + user_id); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "User delete should have returned SL_STATUS_OK"); + + TEST_ASSERT_EQUAL_MESSAGE( + USER_SET_OPERATION_TYPE_DELETE, + operation_type_node.desired(), + "Operation type mismatch for user delete"); + + // Set frame + set_frame.clear(); + set_frame.add(static_cast( + USER_SET_OPERATION_TYPE_DELETE)); + set_frame.add(user_id); + helper_test_get_set_frame_happy_case(USER_SET, + operation_type_node, + set_frame); + + helper_simulate_user_report_frame(USER_SET_OPERATION_TYPE_DELETE, + 0, // Next user id + user_modifier_type, + user_modifier_node_id, + user_id, + user_type, + user_active_state, + credential_rule, + expiring_timeout, + user_name_encoding, + user_name); +} + +void test_user_credential_credential_add_modify_delete_happy_case() +{ + helper_set_version(1); + + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + bool crb = true; + std::string credential_data = "12"; + user_credential_modifier_type_t credential_modifier_type = 2; + user_credential_modifier_node_id_t credential_modifier_node_id = 1212; + + // Simulate user + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Se capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE}; + std::vector supported_cl = {1}; + std::vector supported_credential_slots = {1}; + std::vector supported_cred_min_length = {2}; + std::vector supported_cred_max_length = {6}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1}, + {1}); + + // Add credential + sl_status_t status = zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + credential_data.c_str()); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Credential add should have returned SL_STATUS_OK"); + + // Get credential type + auto credential_type_node + = user_id_node.child_by_type(ATTRIBUTE(CREDENTIAL_TYPE)); + + TEST_ASSERT_TRUE_MESSAGE(credential_type_node.is_valid(), + "Credential type node should exist"); + + // Get credential slot + auto credential_slot_node + = credential_type_node.child_by_type(ATTRIBUTE(CREDENTIAL_SLOT)); + + TEST_ASSERT_TRUE_MESSAGE(credential_slot_node.is_valid(), + "Credential slot node should exist"); + + // Create notification report frame + helper_simulate_credential_report_frame( + 0x00, // Credential add + user_id, + credential_type, + credential_slot, + crb, + string_to_uint8_vector(credential_data), + credential_modifier_type, + credential_modifier_node_id, + 0, + 0); + + // Check values + auto test_attribute_store_values = [&]() { + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type, + user_id_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + credential_type_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MODIFIER_TYPE), + credential_modifier_type, + credential_slot_node); + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_MODIFIER_NODE_ID), + credential_modifier_node_id, + credential_slot_node); + }; + test_attribute_store_values(); + + crb = false; + credential_data = "121212"; + credential_modifier_type = 3; + credential_modifier_node_id = 15; + + // Modify credential + helper_simulate_credential_report_frame( + 0x01, // Credential modify + user_id, + credential_type, + credential_slot, + crb, + string_to_uint8_vector(credential_data), + credential_modifier_type, + credential_modifier_node_id, + 0, + 0); + + test_attribute_store_values(); + + helper_simulate_credential_report_frame( + 0x02, // Credential remove + user_id, + credential_type, + credential_slot, + 0, + string_to_uint8_vector(credential_data), + credential_modifier_type, + credential_modifier_node_id, + 0, + 0); + TEST_ASSERT_FALSE_MESSAGE(credential_slot_node.is_valid(), + "Credential slot node should be deleted"); + TEST_ASSERT_TRUE_MESSAGE(credential_type_node.is_valid(), + "Credential type node should still exist"); + TEST_ASSERT_TRUE_MESSAGE(user_id_node.is_valid(), + "User ID node should still exist"); +} + +void test_user_credential_user_add_capabilites_failure_cases() +{ + // Initialize the notification callback + helper_set_version(1); + + // Those functions are exposed and checks user values, so we need to setup the capabilities + uint16_t number_of_users = 1; + user_credential_supported_credential_rules_t cred_rule_bitmask = 2; + uint8_t username_max_length = 1; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum = 0; + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 1; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 1; + helper_simulate_user_capabilites_report(number_of_users, + cred_rule_bitmask, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + // User ID not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_user(endpoint_id_node, + 12, // User ID + 0, // User Type + 1, // Credential rule + 1, + 0, + 0, + "G"), + "User ID is not valid"); + + // User Type not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_user(endpoint_id_node, + 1, // User ID + 1, // User Type + 1, // Credential rule + 1, + 0, + 0, + "G"), + "User Type is not valid"); + + // Credential rule not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_user(endpoint_id_node, + 1, // User ID + 0, // User Type + 2, // Credential rule + 1, + 0, + 0, + "G"), + "Credential rule is not valid"); + + // Username too long + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_user(endpoint_id_node, + 1, // User ID + 0, // User Type + 1, // Credential rule + 1, + 0, + 0, + "GERARD TURBO"), + "User name is not valid"); +} + +void test_user_credential_user_add_capabilites_happy_cred_rule_cases() +{ + helper_set_version(1); + + uint16_t number_of_users = 1; + uint8_t username_max_length = 1; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum = 0; + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 1; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 1; + + std::map cred_rule_map + = { + {0x02, 1}, + {0x04, 2}, + {0x08, 3}, + {0x06, 1}, + {0x06, 2}, + {0x0F, 3}, + {0x0F, 2}, + {0x0F, 1}, + }; + + for (auto &cred_rule: cred_rule_map) { + helper_simulate_user_capabilites_report(number_of_users, + cred_rule.first, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + printf("Testing bitmask %d with value %d\n", + cred_rule.first, + cred_rule.second); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + zwave_command_class_user_credential_add_new_user( + endpoint_id_node, + 1, // User ID + 0, // User Type + cred_rule.second, // Credential rule + 1, + 0, + 0, + "G"), + "Should be able to add user"); + } +} + +void test_user_credential_user_add_capabilites_happy_user_type_rule_cases() +{ + helper_set_version(1); + + uint16_t number_of_users = 1; + uint8_t username_max_length = 1; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum = 0; + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 1; + user_credential_supported_credential_rules_t cred_rule = 0x02; + + std::map type_rule_map + = { + {0x01, 0}, + {0x02, 1}, + {0x04, 2}, + {0x08, 3}, + {0x06, 1}, + {0x06, 2}, + {0x0F, 3}, + {0x0F, 2}, + {0x0F, 1}, + }; + + for (auto &type_rule: type_rule_map) { + helper_simulate_user_capabilites_report(number_of_users, + cred_rule, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + type_rule.first); + + printf("Testing bitmask %d with value %d\n", + type_rule.first, + type_rule.second); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + zwave_command_class_user_credential_add_new_user( + endpoint_id_node, + 1, // User ID + type_rule.second, // User Type + 1, // Credential rule + 1, + 0, + 0, + "G"), + "Should be able to add user"); + } +} + +void test_user_credential_user_modify_capabilites_failure_cases() +{ + // Initialize the notification callback + helper_set_version(1); + + // Those functions are exposed and checks user values, so we need to setup the capabilities + uint16_t number_of_users = 1; + user_credential_supported_credential_rules_t cred_rule_bitmask = 2; + uint8_t username_max_length = 1; + uint8_t support_user_schedule = 0; + uint8_t support_all_users_checksum = 0; + uint8_t support_user_checksum = 0; + uint8_t supported_user_types_bitmask_length = 1; + user_credential_supported_user_type_bitmask_t supported_user_types_bitmask + = 1; + helper_simulate_user_capabilites_report(number_of_users, + cred_rule_bitmask, + username_max_length, + support_user_schedule, + support_all_users_checksum, + support_user_checksum, + supported_user_types_bitmask_length, + supported_user_types_bitmask); + + // User ID not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + zwave_command_class_user_credential_add_new_user(endpoint_id_node, + 1, // User ID + 0, // User Type + 1, // Credential rule + 1, + 0, + 0, + "G"), + "Should be able to add user"); + + // User Type not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_modify_user(endpoint_id_node, + 1, // User ID + 1, // User Type + 1, // Credential rule + 1, + 0, + 0, + "G"), + "User Type is not valid"); + + // Credential rule not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_modify_user(endpoint_id_node, + 1, // User ID + 0, // User Type + 2, // Credential rule + 1, + 0, + 0, + "G"), + "Credential rule is not valid"); + + // Username too long + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_modify_user(endpoint_id_node, + 1, // User ID + 0, // User Type + 1, // Credential rule + 1, + 0, + 0, + "GERARD TURBO"), + "User name is not valid"); +} + +void test_user_credential_credential_add_capabilites_failure_cases() +{ + // Initialize the notification callback + helper_set_version(1); + + user_credential_user_unique_id_t user_id = 12; + + // Simulate user + attribute_store_emplace(endpoint_id_node, + ATTRIBUTE(USER_UNIQUE_ID), + &user_id, + sizeof(user_id)); + + // Se capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1}; + std::vector supported_credential_slots = {1}; + std::vector supported_cred_min_length = {2}; + std::vector supported_cred_max_length = {6}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1}, + {1}); + + // Credential type not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_PIN_CODE, // Credential type + 1, // Credential slot + "12"), + "Credential type shouldn't be valid"); + + // Credential slot not valid + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 2, // Credential slot + "12"), + "Credential slot shouldn't be valid"); + + // Credential data too short + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 1, + "1"), + "Credential data should be too short"); + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 1, + "TURBO TROP LONG VROUM"), + "Credential data should be too long"); +} + +void test_user_credential_credential_add_capabilites_happy_case() +{ + // Initialize the notification callback + helper_set_version(1); + + user_credential_user_unique_id_t user_id = 12; + + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Se capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_HAND_BIOMETRIC, ZCL_CRED_TYPE_PIN_CODE}; + std::vector supported_cl = {1, 0}; + std::vector supported_credential_slots = {1, 5}; + std::vector supported_cred_min_length = {2, 4}; + std::vector supported_cred_max_length = {6, 8}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1, 1}, + {1, 1}); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 1, + "TURBO"), + "Credential #1 should be valid"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_PIN_CODE, + 4, + "121212"), + "Credential #2 should be valid"); +} + +void test_user_credential_credential_modify_capabilites_failure_cases() +{ + // Initialize the notification callback + helper_set_version(1); + + user_credential_user_unique_id_t user_id = 12; + + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Se capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1}; + std::vector supported_credential_slots = {1}; + std::vector supported_cred_min_length = {2}; + std::vector supported_cred_max_length = {7}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1}, + {1}); + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + zwave_command_class_user_credential_add_new_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 1, + "VOITURE"), + "Should be able to add credential"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_modify_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 1, + "V"), + "Should not be able to modify credential data : it's too short"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + zwave_command_class_user_credential_modify_credential( + endpoint_id_node, + user_id, + ZCL_CRED_TYPE_HAND_BIOMETRIC, + 1, + "MAX SPEEEEEEEEEEEEED TURBO"), + "Should not be able to modify credential data : it's too long"); +} + +void helper_test_credential_rejected_case(uint8_t report_type) +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = 1; + user_credential_slot_t credential_slot = 1; + user_credential_slot_t invalid_credential_slot = 2; + auto credential_data = string_to_uint8_vector("1212"); + + auto valid_user_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + auto valid_cred_type_node + = valid_user_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), credential_type); + auto valid_cred_slot_node + = valid_cred_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + REPORTED_ATTRIBUTE); + auto invalid_cred_slot_node + = valid_cred_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + invalid_credential_slot, + DESIRED_ATTRIBUTE); + invalid_cred_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA), + credential_data, + DESIRED_ATTRIBUTE); + + helper_simulate_credential_report_frame( + report_type, + user_id, + credential_type, + // Duplicate credential send the original slot + report_type == 0x07 ? credential_slot : invalid_credential_slot, + 1, + credential_data, + 0, + 2, + 0, + 0); + + // Here the Credential Report command should remove this not this report + TEST_ASSERT_FALSE_MESSAGE(invalid_cred_slot_node.is_valid(), + "Invalid Credential Slot node should NOT exist"); + TEST_ASSERT_TRUE_MESSAGE(valid_cred_slot_node.is_valid(), + "Valid Credential Slot node SHOULD exist"); + TEST_ASSERT_TRUE_MESSAGE(valid_cred_type_node.is_valid(), + "Valid User node should exist"); + TEST_ASSERT_TRUE_MESSAGE(valid_user_node.is_valid(), + "Valid Credential type node should exist"); +} + +void test_user_credential_credential_set_error_report_cred_add_happy_case() +{ + helper_test_credential_rejected_case(0x05); +} + +void test_user_credential_credential_set_error_report_cred_modify_happy_case() +{ + // Common case + helper_test_credential_rejected_case(0x06); + + // See if that works even without credential type + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), 12); + helper_simulate_credential_report_frame(0x06, + 12, + 5, + 1, + 1, + string_to_uint8_vector("1212"), + 0, + 0, + 0, + 0); +} + +void test_user_credential_credential_set_error_report_cred_duplicate_happy_case() +{ + helper_test_credential_rejected_case(0x07); +} + +void test_user_credential_credential_set_error_report_cred_security_rule_add_happy_case() +{ + helper_test_credential_rejected_case(0x08); +} + +void test_user_credential_credential_set_error_report_cred_security_rule_modify_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = 1; + user_credential_slot_t credential_slot = 1; + uint8_t crb = 1; + auto credential_data = string_to_uint8_vector("1212"); + + auto valid_user_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + auto valid_cred_type_node + = valid_user_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), credential_type); + auto valid_cred_slot_node + = valid_cred_type_node.emplace_node(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot, + REPORTED_ATTRIBUTE); + + auto crb_node + = valid_cred_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_READ_BACK), + crb, + DESIRED_ATTRIBUTE); + auto credential_data_node + = valid_cred_slot_node.emplace_node(ATTRIBUTE(CREDENTIAL_DATA), + credential_data, + DESIRED_ATTRIBUTE); + + helper_simulate_credential_report_frame(0x08, + user_id, + credential_type, + credential_slot, + crb, + credential_data, + 0, + 2, + 0, + 0); + + // Check if the rejected report has cleared all desired values + TEST_ASSERT_FALSE_MESSAGE(crb_node.desired_exists(), + "CRB desired value should NOT exist"); + + TEST_ASSERT_FALSE_MESSAGE(credential_data_node.desired_exists(), + "Credential data desired value should NOT exist"); +} + +void test_user_credential_remove_all_users_happy_case() +{ + helper_set_version(1); + + std::vector user_ids = {0, 12, 15, 19}; + for (auto user_id: user_ids) { + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + } + + auto status + = zwave_command_class_user_credential_delete_all_users(endpoint_id_node); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Remove all users should have returned SL_STATUS_OK"); + + TEST_ASSERT_EQUAL_MESSAGE( + user_ids.size(), + cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(), + "All users should have NOT have been removed yet"); + + // This should remove all users + helper_simulate_user_report_frame(0x02, // Delete user + 0, // Next user id + 0, // User Type + 0, // User Node ID + 0, // User ID + 0, // User Type + 0, // User Active State + 0, // Credential Rule + 0, // Expiring Timeout + 0, // User Name Encoding + ""); // User Name + + TEST_ASSERT_EQUAL_MESSAGE( + 1, // User with ID 0 that might contains credentials + cpp_endpoint_id_node.children(ATTRIBUTE(USER_UNIQUE_ID)).size(), + "Only user 0 should be left"); + + helper_test_attribute_value(ATTRIBUTE(USER_UNIQUE_ID), + static_cast(0)); +} + +// TODO : to be refactored +void test_user_credential_remove_all_credentials_happy_case() +{ + helper_set_version(1); + + std::vector expected_nodes; + // WARNING : All those vectors should be the same size + std::vector user_ids = {12, 12, 12, 15, 19}; + std::vector credential_types = {1, 1, 2, 5, 1}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + expected_nodes.push_back( + helper_create_credential_structure(user_ids[i], + credential_types[i], + credential_slots[i], + REPORTED_ATTRIBUTE)); + } + + auto status = zwave_command_class_user_credential_delete_all_credentials( + endpoint_id_node); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Remove all credentials should have returned SL_STATUS_OK"); + + helper_simulate_credential_report_frame(0x02, 0, 0, 0, 0, {}, 0, 0, 0, 0); + + for (auto &node: expected_nodes) { + TEST_ASSERT_FALSE_MESSAGE(node.credential_type_node.is_valid(), + "Credential type node should have been removed"); + TEST_ASSERT_FALSE_MESSAGE(node.credential_slot_node.is_valid(), + "Credential slot node should have been removed"); + } +} + +/** + * @brief Test the removal of credentials of a user + * + * @param nodes Nodes to tests + * @param deletion_condition If true will test if credential types and slots have been removed, otherwise will test if they still exist + * + */ +void helper_test_credential_structure_exists(credential_structure_nodes nodes, + bool deletion_condition) +{ + if (deletion_condition) { + TEST_ASSERT_FALSE_MESSAGE(nodes.credential_type_node.is_valid(), + "Credential type node should have been removed"); + TEST_ASSERT_FALSE_MESSAGE(nodes.credential_slot_node.is_valid(), + "Credential slot node should have been removed"); + } else { + TEST_ASSERT_TRUE_MESSAGE(nodes.credential_type_node.is_valid(), + "Credential type node should still exist"); + TEST_ASSERT_TRUE_MESSAGE(nodes.credential_slot_node.is_valid(), + "Credential slot node should still exist"); + } +} + +void test_user_credential_remove_all_credentials_of_user() +{ + helper_set_version(1); + + user_credential_user_unique_id_t user_to_delete = 12; + + std::vector expected_nodes; + // WARNING : All those vectors should be the same size + std::vector user_ids + = {user_to_delete, user_to_delete, user_to_delete, 15, 19}; + std::vector credential_types = {1, 1, 2, 5, 1}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + expected_nodes.push_back( + helper_create_credential_structure(user_ids[i], + credential_types[i], + credential_slots[i], + REPORTED_ATTRIBUTE)); + } + + auto status + = zwave_command_class_user_credential_delete_all_credentials_for_user( + endpoint_id_node, + user_to_delete); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Remove all credentials for user should have returned SL_STATUS_OK"); + + helper_simulate_credential_report_frame(0x02, + user_to_delete, + 0, + 0, + 0, + {}, + 0, + 0, + 0, + 0); + + for (auto &node: expected_nodes) { + auto reported_user_id + = node.user_id_node.reported(); + node.print(); + + helper_test_credential_structure_exists(node, + reported_user_id == user_to_delete); + } +} + +struct expected_node_data { + credential_structure_nodes nodes; + bool deletion_condition; +}; +void test_user_credential_remove_all_credentials_of_user_by_type() +{ + helper_set_version(1); + + user_credential_user_unique_id_t user_to_delete = 12; + user_credential_type_t credential_type_to_delete = 1; + + std::vector expected_nodes_data; + // WARNING : All those vectors should be the same size + std::vector user_ids + = {user_to_delete, user_to_delete, user_to_delete, 15, 19}; + std::vector credential_types + = {credential_type_to_delete, credential_type_to_delete, 2, 5, 1}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + expected_nodes_data.push_back( + {helper_create_credential_structure(user_ids[i], + credential_types[i], + credential_slots[i], + REPORTED_ATTRIBUTE), + user_ids[i] == user_to_delete + && credential_types[i] == credential_type_to_delete}); + } + + auto status + = zwave_command_class_user_credential_delete_all_credentials_for_user_by_type( + endpoint_id_node, + user_to_delete, + credential_type_to_delete); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Remove all credentials for user should have returned SL_STATUS_OK"); + + helper_simulate_credential_report_frame(0x02, + user_to_delete, + credential_type_to_delete, + 0, + 0, + {}, + 0, + 0, + 0, + 0); + + for (auto &node_data: expected_nodes_data) { + auto nodes = node_data.nodes; + auto deletion_condition = node_data.deletion_condition; + + nodes.print(); + helper_test_credential_structure_exists(nodes, deletion_condition); + } +} + +void test_user_credential_remove_all_credentials_by_type() +{ + helper_set_version(1); + + user_credential_type_t credential_type_to_delete = 1; + + std::vector expected_nodes_data; + // WARNING : All those vectors should be the same size + std::vector user_ids = {12, 12, 12, 15, 19}; + std::vector credential_types + = {credential_type_to_delete, + credential_type_to_delete, + 2, + 5, + credential_type_to_delete}; + std::vector credential_slots = {1, 2, 2, 1, 3}; + // WARNING : Make sure that all the vector above have the same size + const size_t expected_credential_count = user_ids.size(); + for (size_t i = 0; i < expected_credential_count; i++) { + expected_nodes_data.push_back( + {helper_create_credential_structure(user_ids[i], + credential_types[i], + credential_slots[i], + REPORTED_ATTRIBUTE), + credential_types[i] == credential_type_to_delete}); + } + + auto status + = zwave_command_class_user_credential_delete_all_credentials_by_type( + endpoint_id_node, + credential_type_to_delete); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_OK, + status, + "Remove all credentials for user should have returned SL_STATUS_OK"); + + helper_simulate_credential_report_frame(0x02, + 0, + credential_type_to_delete, + 0, + 0, + {}, + 0, + 0, + 0, + 0); + + for (auto &node_data: expected_nodes_data) { + auto nodes = node_data.nodes; + auto deletion_condition = node_data.deletion_condition; + + nodes.print(); + helper_test_credential_structure_exists(nodes, deletion_condition); + } +} + +void test_user_credential_credential_learn_start_add_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {20, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + // Add credential + // Test if we give 0 as timeout, it should be set to default value + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_add( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Should be able to start learning"); + + attribute_store::attribute credential_type_node; + attribute_store::attribute credential_slot_node; + auto update_credential_nodes = [&]() { + credential_type_node + = user_id_node.child_by_type_and_value(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type); + + credential_slot_node + = credential_type_node.child_by_type_and_value(ATTRIBUTE(CREDENTIAL_SLOT), + credential_slot); + }; + + update_credential_nodes(); + helper_test_credential_learn_structure(user_id_node, + credential_type_node, + credential_slot_node, + supported_cl_timeout[0], + USER_CREDENTIAL_OPERATION_TYPE_ADD); + + // Test with specific timeout + credential_type = ZCL_CRED_TYPE_HAND_BIOMETRIC; + credential_slot = 1; + cl_timeout = 100; + + status = zwave_command_class_user_credential_credential_learn_start_add( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Should be able to start learning"); + + update_credential_nodes(); + helper_test_credential_learn_structure(user_id_node, + credential_type_node, + credential_slot_node, + cl_timeout, + USER_CREDENTIAL_OPERATION_TYPE_ADD); +} + +void test_user_credential_credential_learn_start_add_cl_not_supported() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {0, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {0, 2}; + std::vector supported_cl_steps = {0, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_add( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Should not be able to start learning"); +} + +void test_user_credential_credential_learn_start_add_slot_not_supported() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 6; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {10, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_add( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Should not be able to start learning"); +} + +void test_user_credential_credential_learn_start_add_type_not_supported() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_BLE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {10, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_add( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Should not be able to start learning"); +} + +void test_user_credential_credential_learn_start_add_credential_already_exists() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Simulate already existing credential + user_id = 15; + helper_create_credential_structure(user_id, + credential_type, + credential_slot, + REPORTED_ATTRIBUTE); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {10, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_add( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Should not be able to start learning"); +} + +void test_user_credential_credential_learn_start_modify_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + auto credential_nodes + = helper_create_credential_structure(user_id, + credential_type, + credential_slot, + REPORTED_ATTRIBUTE); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {20, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + // Add credential + // Test if we give 0 as timeout, it should be set to default value + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_modify( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Should be able to start learning (modify)"); + + helper_test_credential_learn_structure(credential_nodes.user_id_node, + credential_nodes.credential_type_node, + credential_nodes.credential_slot_node, + supported_cl_timeout[0], + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); + + // Test with specific timeout + credential_type = ZCL_CRED_TYPE_HAND_BIOMETRIC; + credential_slot = 1; + cl_timeout = 100; + credential_nodes = helper_create_credential_structure(user_id, + credential_type, + credential_slot, + REPORTED_ATTRIBUTE); + + status = zwave_command_class_user_credential_credential_learn_start_modify( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Should be able to start learning (modify)"); + helper_test_credential_learn_structure(credential_nodes.user_id_node, + credential_nodes.credential_type_node, + credential_nodes.credential_slot_node, + cl_timeout, + USER_CREDENTIAL_OPERATION_TYPE_MODIFY); +} + +void test_user_credential_credential_learn_start_modify_cl_not_supported() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + // Simulate user + helper_create_credential_structure(user_id, + credential_type, + credential_slot, + REPORTED_ATTRIBUTE); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {0, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {0, 2}; + std::vector supported_cl_steps = {0, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_modify( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Should not be able to start learning (modify)"); +} + +void test_user_credential_credential_learn_start_modify_credential_not_existing() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t credential_slot = 1; + user_credential_learn_timeout_t cl_timeout = 0; + + // Simulate user + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), user_id); + + // Set capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {0, 1}; + std::vector supported_credential_slots = {1, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {0, 2}; + std::vector supported_cl_steps = {0, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + sl_status_t status + = zwave_command_class_user_credential_credential_learn_start_modify( + endpoint_id_node, + user_id, + credential_type, + credential_slot, + cl_timeout); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Should not be able to start learning (modify)"); +} + +void test_user_credential_credential_learn_cancel_happy_case() +{ + uint8_t stop_flag = 0; + auto stop_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_LEARN_STOP), + stop_flag, + DESIRED_ATTRIBUTE); + + helper_test_get_set_frame_happy_case(CREDENTIAL_LEARN_CANCEL, stop_node); + + TEST_ASSERT_EQUAL_MESSAGE(1, + stop_node.reported(), + "Stop flag should have been set to 1"); +} + +void test_user_credential_uuic_association_same_slot_different_user() +{ + // Capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {5, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {20, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + // Structure + user_credential_user_unique_id_t source_user_id = 12; + user_credential_user_unique_id_t destination_user_id = 15; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t source_credential_slot = 1; + user_credential_slot_t destination_credential_slot = 1; + // Credential data + std::string credential_data = "123456"; + user_credential_modifier_type_t modifier_type = 5; + uint8_t association_status = USER_CREDENTIAL_ASSOCIATION_REPORT_SUCCESS; + + auto source_nodes = helper_create_credential_structure(source_user_id, + credential_type, + source_credential_slot, + REPORTED_ATTRIBUTE); + + auto destination_user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + destination_user_id); + + helper_fill_credential_data(source_nodes.credential_slot_node, + credential_data, + modifier_type); + auto association_nodes + = helper_setup_association(source_nodes.credential_slot_node, + destination_user_id, + destination_credential_slot); + // Simulate Set + zwave_frame set_frame; + set_frame.add(source_user_id); + set_frame.add(credential_type); + set_frame.add(source_credential_slot); + set_frame.add(destination_user_id); + set_frame.add(destination_credential_slot); + + helper_test_get_set_frame_happy_case( + USER_CREDENTIAL_ASSOCIATION_SET, + association_nodes.association_credential_slot_node, + set_frame); + + // Then simulate report + helper_simulate_association_report_frame(source_user_id, + credential_type, + source_credential_slot, + destination_user_id, + destination_credential_slot, + association_status); + + // Test data structure + TEST_ASSERT_TRUE_MESSAGE(source_nodes.credential_type_node.is_valid(), + "Old credential type node should still exist"); + // Association nodes doesn't have any reported value so they shouldn't exists anymore + TEST_ASSERT_FALSE_MESSAGE( + association_nodes.association_user_id_node.is_valid(), + "Association user id node should have been removed"); + TEST_ASSERT_FALSE_MESSAGE( + association_nodes.association_credential_slot_node.is_valid(), + "Association credential slot node should have been removed"); + + TEST_ASSERT_EQUAL_MESSAGE( + 0, + source_nodes.credential_type_node.child_count(), + "Source Credential type node should have no children"); + + // Check destination structure + auto destination_credential_type_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type, + destination_user_id_node); + TEST_ASSERT_EQUAL_MESSAGE(source_nodes.credential_slot_node.parent(), + destination_credential_type_node, + "Old credential slot node should have new parent"); + + auto destination_credential_slot_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_SLOT), + destination_credential_slot, + destination_credential_type_node); + + helper_test_credential_data(destination_credential_slot_node, + credential_data, + modifier_type); + + helper_test_attribute_value(ATTRIBUTE(ASSOCIATION_STATUS), + association_status, + destination_credential_slot_node); +} + +void test_user_credential_uuic_association_different_slot_different_user_with_existing_type() +{ + // Capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {5, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {20, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + // Structure + user_credential_user_unique_id_t source_user_id = 12; + user_credential_user_unique_id_t destination_user_id = 15; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t source_credential_slot = 1; + user_credential_slot_t destination_credential_slot = 2; + // Credential data + std::string credential_data = "123456"; + user_credential_modifier_type_t modifier_type = 5; + uint8_t association_status = USER_CREDENTIAL_ASSOCIATION_REPORT_SUCCESS; + + auto source_nodes = helper_create_credential_structure(source_user_id, + credential_type, + source_credential_slot, + REPORTED_ATTRIBUTE); + + auto destination_user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + destination_user_id); + // Already present type + destination_user_id_node.emplace_node(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type); + + helper_fill_credential_data(source_nodes.credential_slot_node, + credential_data, + modifier_type); + auto association_nodes + = helper_setup_association(source_nodes.credential_slot_node, + destination_user_id, + destination_credential_slot); + + // Simulate Set + zwave_frame set_frame; + set_frame.add(source_user_id); + set_frame.add(credential_type); + set_frame.add(source_credential_slot); + set_frame.add(destination_user_id); + set_frame.add(destination_credential_slot); + + helper_test_get_set_frame_happy_case( + USER_CREDENTIAL_ASSOCIATION_SET, + association_nodes.association_credential_slot_node, + set_frame); + + // Then simulate report + helper_simulate_association_report_frame(source_user_id, + credential_type, + source_credential_slot, + destination_user_id, + destination_credential_slot, + association_status); + + // Test data structure + TEST_ASSERT_TRUE_MESSAGE(source_nodes.credential_type_node.is_valid(), + "Old credential type node should still exist"); + // Association nodes doesn't have any reported value so they shouldn't exists anymore + TEST_ASSERT_FALSE_MESSAGE( + association_nodes.association_user_id_node.is_valid(), + "Association user id node should have been removed"); + TEST_ASSERT_FALSE_MESSAGE( + association_nodes.association_credential_slot_node.is_valid(), + "Association credential slot node should have been removed"); + + TEST_ASSERT_EQUAL_MESSAGE( + 0, + source_nodes.credential_type_node.child_count(), + "Source Credential type node should have no children"); + + // Check destination structure + auto destination_credential_type_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type, + destination_user_id_node); + + TEST_ASSERT_EQUAL_MESSAGE(source_nodes.credential_slot_node.parent(), + destination_credential_type_node, + "Old credential slot node should have new parent"); + + auto destination_credential_slot_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_SLOT), + destination_credential_slot, + destination_credential_type_node); + + helper_test_credential_data(destination_credential_slot_node, + credential_data, + modifier_type); + + helper_test_attribute_value(ATTRIBUTE(ASSOCIATION_STATUS), + association_status, + destination_credential_slot_node); +} + +void test_user_credential_uuic_association_different_slot_same_user() +{ + // Capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {5, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {20, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + // Structure + user_credential_user_unique_id_t source_user_id = 12; + user_credential_user_unique_id_t destination_user_id = 12; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t source_credential_slot = 1; + user_credential_slot_t destination_credential_slot = 2; + // Credential data + std::string credential_data = "123456"; + user_credential_modifier_type_t modifier_type = 5; + uint8_t association_status = USER_CREDENTIAL_ASSOCIATION_REPORT_SUCCESS; + + auto source_nodes = helper_create_credential_structure(source_user_id, + credential_type, + source_credential_slot, + REPORTED_ATTRIBUTE); + + helper_fill_credential_data(source_nodes.credential_slot_node, + credential_data, + modifier_type); + auto association_nodes + = helper_setup_association(source_nodes.credential_slot_node, + destination_user_id, + destination_credential_slot); + // Simulate Set + zwave_frame set_frame; + set_frame.add(source_user_id); + set_frame.add(credential_type); + set_frame.add(source_credential_slot); + set_frame.add(destination_user_id); + set_frame.add(destination_credential_slot); + + helper_test_get_set_frame_happy_case( + USER_CREDENTIAL_ASSOCIATION_SET, + association_nodes.association_credential_slot_node, + set_frame); + + // Then simulate report + helper_simulate_association_report_frame(source_user_id, + credential_type, + source_credential_slot, + destination_user_id, + destination_credential_slot, + association_status); + + // Test data structure + TEST_ASSERT_TRUE_MESSAGE( + attribute_store_node_exists(source_nodes.credential_type_node), + "Old credential type node should still exist"); + TEST_ASSERT_TRUE_MESSAGE( + attribute_store_node_exists(source_nodes.credential_slot_node), + "Old credential slot node should just been updated"); + // Association nodes doesn't have any reported value so they shouldn't exists anymore + TEST_ASSERT_FALSE_MESSAGE( + attribute_store_node_exists(association_nodes.association_user_id_node), + "Association user id node should have been removed"); + TEST_ASSERT_FALSE_MESSAGE( + attribute_store_node_exists( + association_nodes.association_credential_slot_node), + "Association credential slot node should have been removed"); + + TEST_ASSERT_EQUAL_MESSAGE( + 1, + attribute_store_get_node_child_count(source_nodes.credential_type_node), + "Source Credential type node should have one children"); + + // Check destination structure + auto destination_credential_type_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_TYPE), + credential_type, + source_nodes.user_id_node); + + auto destination_credential_slot_node + = helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_SLOT), + destination_credential_slot, + destination_credential_type_node); + + helper_test_credential_data(destination_credential_slot_node, + credential_data, + modifier_type); + + helper_test_attribute_value(ATTRIBUTE(ASSOCIATION_STATUS), + association_status, + destination_credential_slot_node); +} + +void test_user_credential_uuic_association_error_code() +{ + // Capabilities + uint8_t supported_credential_checksum = 1; + uint8_t support_admin_code = 1; + uint8_t support_admin_code_deactivation = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector supported_cl = {1, 1}; + std::vector supported_credential_slots = {5, 2}; + std::vector supported_cred_min_length = {2, 5}; + std::vector supported_cred_max_length = {6, 10}; + std::vector supported_cl_timeout = {20, 2}; + std::vector supported_cl_steps = {1, 95}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + supported_cl_timeout, + supported_cl_steps); + + // Structure + user_credential_user_unique_id_t source_user_id = 12; + user_credential_user_unique_id_t destination_user_id = 15; + user_credential_type_t credential_type = ZCL_CRED_TYPE_PIN_CODE; + user_credential_slot_t source_credential_slot = 1; + user_credential_slot_t destination_credential_slot = 1; + // Credential data + std::string credential_data = "123456"; + user_credential_modifier_type_t modifier_type = 5; + uint8_t association_status + = USER_CREDENTIAL_ASSOCIATION_REPORT_SOURCE_CREDENTIAL_SLOT_EMPTY; + + auto source_nodes = helper_create_credential_structure(source_user_id, + credential_type, + source_credential_slot, + REPORTED_ATTRIBUTE); + + auto destination_user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + destination_user_id); + + helper_fill_credential_data(source_nodes.credential_slot_node, + credential_data, + modifier_type); + auto association_nodes + = helper_setup_association(source_nodes.credential_slot_node, + destination_user_id, + destination_credential_slot); + // Simulate Set + zwave_frame set_frame; + set_frame.add(source_user_id); + set_frame.add(credential_type); + set_frame.add(source_credential_slot); + set_frame.add(destination_user_id); + set_frame.add(destination_credential_slot); + + helper_test_get_set_frame_happy_case( + USER_CREDENTIAL_ASSOCIATION_SET, + association_nodes.association_credential_slot_node, + set_frame); + + // Then simulate report + helper_simulate_association_report_frame(source_user_id, + credential_type, + source_credential_slot, + destination_user_id, + destination_credential_slot, + association_status); + + // Test data structure + TEST_ASSERT_TRUE_MESSAGE( + attribute_store_node_exists(source_nodes.credential_type_node), + "Old credential type node should still exist"); + TEST_ASSERT_TRUE_MESSAGE( + attribute_store_node_exists(source_nodes.credential_slot_node), + "Old credential slot node should still exists"); + // Association nodes doesn't have any reported value so they shouldn't exists anymore + TEST_ASSERT_FALSE_MESSAGE( + attribute_store_node_exists(association_nodes.association_user_id_node), + "Association user id node should have been removed"); + TEST_ASSERT_FALSE_MESSAGE( + attribute_store_node_exists( + association_nodes.association_credential_slot_node), + "Association credential slot node should have been removed"); + + TEST_ASSERT_EQUAL_MESSAGE( + 1, + attribute_store_get_node_child_count(source_nodes.credential_type_node), + "Source Credential type node should have one children"); + + // No move should have been performed + TEST_ASSERT_EQUAL_MESSAGE( + 0, + attribute_store_get_node_child_count(destination_user_id_node), + "Nothing should have changed for destination user ID node"); + + // Test source credential slot node + auto destination_credential_slot_node = source_nodes.credential_slot_node; + helper_test_attribute_value(ATTRIBUTE(CREDENTIAL_SLOT), + destination_credential_slot, + source_nodes.credential_type_node); + + helper_test_credential_data(destination_credential_slot_node, + credential_data, + modifier_type); + + helper_test_attribute_value(ATTRIBUTE(ASSOCIATION_STATUS), + association_status, + destination_credential_slot_node); +} + +void test_get_user_checksum_with_credentials_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_user_type_t user_type = 0x04; + user_credential_user_active_state_t user_active_state = 0x01; + user_credential_supported_credential_rules_t credential_rules = 0x01; + user_credential_user_name_encoding_t user_name_encoding = 0x00; + std::string user_name = "Matt"; + + // Creating user + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + DESIRED_ATTRIBUTE); + + // Simulate get/report on user + zwave_frame user_get_frame; + user_get_frame.add(user_id); + helper_test_get_set_frame_happy_case(USER_GET, user_id_node, user_get_frame); + + helper_simulate_user_report_frame(0x04, + 0, + 0x02, // Z-Wave + 0, + user_id, + user_type, + user_active_state, + credential_rules, + 0, + user_name_encoding, + user_name); + + // Credentials + std::vector credential_types + = {ZCL_CRED_TYPE_PIN_CODE, + ZCL_CRED_TYPE_PIN_CODE, + ZCL_CRED_TYPE_PASSWORD, + ZCL_CRED_TYPE_HAND_BIOMETRIC}; + std::vector credential_slots = {2, 4, 1, 8}; + + std:: + vector> + credential_data = { + {0x39, 0x32, 0x37, 0x37}, // "9277" in ASCII + {0x39, 0x35, 0x34, 0x39, 0x38, 0x38}, // "954988" in ASCII + { + 0x00, 0x7A, 0x00, 0x77, 0x00, 0x61, 0x00, 0x76, 0x00, + 0x65, 0x00, 0x6E, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, + 0x00, 0x70, 0x00, 0x61, 0x00, 0x73, 0x00, 0x73, 0x00, + 0x77, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x64}, // zwavenodepassword in Unicode UTF-16 format, in big endian order, + {0x71, 0x99} // Raw data + }; + + if (credential_types.size() != credential_slots.size() + || credential_slots.size() != credential_data.size()) { + TEST_FAIL_MESSAGE("All vectors should be the same size"); + } + + for (size_t i = 0; i < credential_types.size(); i++) { + helper_simulate_credential_report_frame( + 0x00, + user_id, + credential_types[i], + credential_slots[i], + 0, + credential_data[i], + 0x02, // Anything but 0 + 0, + (i + 1) == credential_types.size() ? 0 : credential_types[i + 1], + (i + 1) == credential_types.size() ? 0 : credential_slots[i + 1]); + } + + // Get checksum + auto checksum_node = user_id_node.add_node(ATTRIBUTE(USER_CHECKSUM)); + + zwave_frame checksum_get_frame; + checksum_get_frame.add(user_id); + + helper_test_get_set_frame_happy_case(USER_CHECKSUM_GET, + checksum_node, + checksum_get_frame); + + user_credential_checksum_t expected_checksum = 0x9024; + helper_simulate_user_checksum_report(user_id, expected_checksum); + + // Check if checksum is correct + TEST_ASSERT_EQUAL_MESSAGE( + expected_checksum, + checksum_node.reported(), + "Checksum mismatch"); +} + +void test_get_user_checksum_without_credentials_happy_case() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_user_type_t user_type = 0x04; + user_credential_user_active_state_t user_active_state = 0x01; + user_credential_supported_credential_rules_t credential_rules = 0x01; + user_credential_user_name_encoding_t user_name_encoding = 0x00; + std::string user_name = "Lillie"; + + // Creating user + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + DESIRED_ATTRIBUTE); + + // Simulate get/report on user + zwave_frame user_get_frame; + user_get_frame.add(user_id); + helper_test_get_set_frame_happy_case(USER_GET, user_id_node, user_get_frame); + + helper_simulate_user_report_frame(0x04, + 0, + 0x02, // Z-Wave + 0, + user_id, + user_type, + user_active_state, + credential_rules, + 0, + user_name_encoding, + user_name); + + // Get checksum + auto checksum_node = user_id_node.add_node(ATTRIBUTE(USER_CHECKSUM)); + + zwave_frame checksum_get_frame; + checksum_get_frame.add(user_id); + + helper_test_get_set_frame_happy_case(USER_CHECKSUM_GET, + checksum_node, + checksum_get_frame); + + user_credential_checksum_t expected_checksum = 0xF900; + helper_simulate_user_checksum_report(user_id, expected_checksum); + + // Check if checksum is correct + TEST_ASSERT_EQUAL_MESSAGE( + expected_checksum, + checksum_node.reported(), + "Checksum mismatch"); +} + +void test_get_user_checksum_without_credentials_mismatch_checksum() +{ + user_credential_user_unique_id_t user_id = 12; + user_credential_user_type_t user_type = 0x04; + user_credential_user_active_state_t user_active_state = 0x01; + user_credential_supported_credential_rules_t credential_rules = 0x01; + user_credential_user_name_encoding_t user_name_encoding = 0x00; + std::string user_name = "Lillie"; + + // Creating user + auto user_id_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(USER_UNIQUE_ID), + user_id, + DESIRED_ATTRIBUTE); + + // Simulate get/report on user + zwave_frame user_get_frame; + user_get_frame.add(user_id); + helper_test_get_set_frame_happy_case(USER_GET, user_id_node, user_get_frame); + + helper_simulate_user_report_frame(0x04, + 0, + 0x02, // Z-Wave + 0, + user_id, + user_type, + user_active_state, + credential_rules, + 0, + user_name_encoding, + user_name); + // Get checksum + auto checksum_node = user_id_node.add_node(ATTRIBUTE(USER_CHECKSUM)); + + zwave_frame checksum_get_frame; + checksum_get_frame.add(user_id); + + helper_test_get_set_frame_happy_case(USER_CHECKSUM_GET, + checksum_node, + checksum_get_frame); + + // Simulate checksum mismatch + user_credential_checksum_t expected_checksum = 0xF900; + user_credential_checksum_t error_expected_checksum = expected_checksum + 1; + helper_simulate_user_checksum_report(user_id, + error_expected_checksum, + SL_STATUS_FAIL); + + // Check if checksum is correct + TEST_ASSERT_EQUAL_MESSAGE( + error_expected_checksum, + checksum_node.reported(), + "Calculated checksum mismatch"); + + auto error_checksum_node + = helper_test_attribute_value(ATTRIBUTE(USER_CHECKSUM_MISMATCH_ERROR), + expected_checksum, + user_id_node); + + // Now simulate checksum match + helper_simulate_user_checksum_report(user_id, expected_checksum); + + TEST_ASSERT_EQUAL_MESSAGE( + expected_checksum, + checksum_node.reported(), + "Calculated checksum mismatch"); + + TEST_ASSERT_FALSE_MESSAGE(error_checksum_node.is_valid(), + "Error node should have been removed"); +} + +void test_get_credential_checksum_happy_case() +{ + helper_create_credential_checksum_structure(); + + std::vector tested_credential_types + = {ZCL_CRED_TYPE_PIN_CODE, + ZCL_CRED_TYPE_PASSWORD, + ZCL_CRED_TYPE_EYE_BIOMETRIC, + ZCL_CRED_TYPE_RFID_CODE}; + + std::vector expected_checksums + = {0xD867, 0x6F76, 0xC06E, 0x0000}; + + // Create empty RFID_CODE + user_credential_type_t rfid_type = ZCL_CRED_TYPE_RFID_CODE; + cpp_endpoint_id_node.emplace_node(ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + rfid_type); + + if (tested_credential_types.size() != expected_checksums.size()) { + TEST_FAIL_MESSAGE("All vectors should be the same size"); + } + + for (size_t i = 0; i < tested_credential_types.size(); i++) { + auto current_credential_type = tested_credential_types[i]; + auto current_credential_type_node + = cpp_endpoint_id_node.child_by_type_and_value( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + current_credential_type); + + TEST_ASSERT_TRUE_MESSAGE(current_credential_type_node.is_valid(), + "Credential type node should exist"); + + // Get checksum + auto checksum_node + = current_credential_type_node.add_node(ATTRIBUTE(CREDENTIAL_CHECKSUM)); + + zwave_frame checksum_get_frame; + checksum_get_frame.add(current_credential_type); + + helper_test_get_set_frame_happy_case(CREDENTIAL_CHECKSUM_GET, + checksum_node, + checksum_get_frame); + + user_credential_checksum_t expected_checksum = expected_checksums[i]; + helper_simulate_credential_checksum_report(current_credential_type, + expected_checksum); + + // Check if checksum is correct + TEST_ASSERT_EQUAL_MESSAGE( + expected_checksum, + checksum_node.reported(), + (std::string("Checksum mismatch for type ") + + std::to_string(current_credential_type)) + .c_str()); + } +} + +void test_get_credential_checksum_mismatch() +{ + helper_create_credential_checksum_structure(); + + std::vector tested_credential_types + = {ZCL_CRED_TYPE_PIN_CODE, ZCL_CRED_TYPE_PASSWORD}; + + std::vector expected_checksums = {0xD867, 0x6F76}; + + if (tested_credential_types.size() != expected_checksums.size()) { + TEST_FAIL_MESSAGE("All vectors should be the same size"); + } + + for (size_t i = 0; i < tested_credential_types.size(); i++) { + auto current_credential_type = tested_credential_types[i]; + auto current_credential_type_node + = cpp_endpoint_id_node.child_by_type_and_value( + ATTRIBUTE(SUPPORTED_CREDENTIAL_TYPE), + current_credential_type); + + TEST_ASSERT_TRUE_MESSAGE(current_credential_type_node.is_valid(), + "Credential type node should exist"); + + // Get checksum + auto checksum_node + = current_credential_type_node.add_node(ATTRIBUTE(CREDENTIAL_CHECKSUM)); + + zwave_frame checksum_get_frame; + checksum_get_frame.add(current_credential_type); + + helper_test_get_set_frame_happy_case(CREDENTIAL_CHECKSUM_GET, + checksum_node, + checksum_get_frame); + + user_credential_checksum_t error_checksum = expected_checksums[i] + 1; + helper_simulate_credential_checksum_report(current_credential_type, + error_checksum, + SL_STATUS_FAIL); + + // Check error checksum + TEST_ASSERT_EQUAL_MESSAGE( + error_checksum, + checksum_node.reported(), + "Reported checksum mismatch"); + + auto mismatch_checksum_node = helper_test_attribute_value( + ATTRIBUTE(CREDENTIAL_CHECKSUM_MISMATCH_ERROR), + expected_checksums[i], + current_credential_type_node); + + // Try again with correct checksum + + user_credential_checksum_t expected_checksum = expected_checksums[i]; + helper_simulate_credential_checksum_report(current_credential_type, + expected_checksum); + + // Check if checksum is correct + TEST_ASSERT_EQUAL_MESSAGE( + expected_checksum, + checksum_node.reported(), + "Checksum mismatch"); + + TEST_ASSERT_FALSE_MESSAGE( + mismatch_checksum_node.is_valid(), + "Mismatch checksum node should have been removed"); + } +} + +//////////////////////////////////////////////////////////////////////////// +// All User Checksum Get/Report +//////////////////////////////////////////////////////////////////////////// +void test_user_credential_all_users_checksum_get_happy_case() +{ + helper_test_get_set_frame_happy_case(ALL_USERS_CHECKSUM_GET); +} + +void test_user_credential_all_users_checksum_report_no_users_happy_case() +{ + user_credential_all_users_checksum_t expected_checksum = 0x00; + + // Report frame + zwave_frame report_frame; + report_frame.add(expected_checksum); + helper_test_report_frame(ALL_USERS_CHECKSUM_REPORT, report_frame); + + // Attribute store test + helper_test_attribute_value(ATTRIBUTE(ALL_USERS_CHECKSUM), expected_checksum); +} + +void test_user_credential_all_users_checksum_report_with_users_happy_case() +{ + user_credential_all_users_checksum_t expected_checksum = 0x57b9; + + // Add 2 users and one with credentials + helper_simulate_user_report_frame(0x00, // User Add + 0, + 0, + 0, + 12, + 1, + 1, + 15, + 0, + 0, + "MICHEL"); + helper_simulate_user_report_frame(0x00, // User Add + 0, + 0, + 0, + 1312, + 1, + 1, + 15, + 0, + 0, + "TURBO"); + helper_simulate_credential_report_frame(0x00, // Credential Add + 12, + 1, + 1, + 0, + string_to_uint8_vector("1234"), + 0x02, + 0, + 0, + 0); + // Report frame + zwave_frame report_frame; + report_frame.add(expected_checksum); + helper_test_report_frame(ALL_USERS_CHECKSUM_REPORT, report_frame); + + // Attribute store test + helper_test_attribute_value(ATTRIBUTE(ALL_USERS_CHECKSUM), expected_checksum); +} + +//////////////////////////////////////////////////////////////////////////// +// Admin PIN code Set/Get/Support +//////////////////////////////////////////////////////////////////////////// +void test_user_credential_admin_pin_code_get_happy_case() +{ + helper_test_get_set_frame_happy_case(ADMIN_PIN_CODE_GET); +} + +void helper_setup_credential_capabilities_admin_code( + uint8_t support_admin_code = 1, uint8_t support_admin_code_deactivation = 1) +{ + uint8_t supported_credential_checksum = 1; + std::vector supported_credential_type + = {ZCL_CRED_TYPE_PIN_CODE}; + std::vector supported_cl = {1}; + std::vector supported_credential_slots = {1}; + std::vector supported_cred_min_length = {2}; + std::vector supported_cred_max_length = {6}; + helper_simulate_credential_capabilites_report(supported_credential_checksum, + support_admin_code, + support_admin_code_deactivation, + supported_credential_type, + supported_cl, + supported_credential_slots, + supported_cred_min_length, + supported_cred_max_length, + {1}, + {1}); +} +void test_user_credential_admin_pin_code_set_happy_case() +{ + helper_setup_credential_capabilities_admin_code(); + + std::string admin_pin_code = "1312"; + auto admin_pin_code_data = string_to_uint8_vector(admin_pin_code); + + auto status = zwave_command_class_user_credential_set_admin_pin_code( + endpoint_id_node, + admin_pin_code.c_str()); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Set Admin PIN API command should have worked"); + + auto admin_pin_code_node + = helper_test_and_get_node(ATTRIBUTE(ADMIN_PIN_CODE)); + + zwave_frame set_frame; + set_frame.add(admin_pin_code_data); + + helper_test_get_set_frame_happy_case(ADMIN_PIN_CODE_SET, + admin_pin_code_node, + set_frame); +} + +void test_user_credential_admin_pin_code_set_deactivation_happy_case() +{ + helper_setup_credential_capabilities_admin_code(); + + auto status + = zwave_command_class_user_credential_set_admin_pin_code(endpoint_id_node, + ""); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, + status, + "Set Admin PIN API command should have worked"); + + auto admin_pin_code_node + = helper_test_and_get_node(ATTRIBUTE(ADMIN_PIN_CODE)); + + zwave_frame set_frame; + set_frame.add(static_cast(0)); + helper_test_get_set_frame_happy_case(ADMIN_PIN_CODE_SET, + admin_pin_code_node, + set_frame); +} + +void test_user_credential_admin_pin_code_set_deactivation_not_supported() +{ + helper_setup_credential_capabilities_admin_code(1, 0); + + auto status + = zwave_command_class_user_credential_set_admin_pin_code(endpoint_id_node, + ""); + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + status, + "Set Admin PIN API command should NOT have worked"); + + auto admin_pin_code_node + = helper_test_and_get_node(ATTRIBUTE(ADMIN_PIN_CODE)); + + helper_test_get_set_fail_case(ADMIN_PIN_CODE_SET, + SL_STATUS_NOT_SUPPORTED, + admin_pin_code_node); +} + +void test_user_credential_admin_pin_code_report_happy_case() +{ + auto expected_admin_pin_code = string_to_uint8_vector("1312"); + uint8_t admin_pin_code_size + = static_cast(expected_admin_pin_code.size()); + uint8_t expected_operation_result = 0x04; + + // Report frame + zwave_frame report_frame; + uint8_t size_byte = (expected_operation_result << 4) | admin_pin_code_size; + report_frame.add(size_byte); + for (uint8_t c: expected_admin_pin_code) { + report_frame.add(c); + } + + helper_test_report_frame(ADMIN_PIN_CODE_REPORT, report_frame); + + // Attribute store test + helper_test_attribute_value(ATTRIBUTE(ADMIN_PIN_CODE_OPERATION_RESULT), + expected_operation_result); + helper_test_attribute_value(ATTRIBUTE(ADMIN_PIN_CODE), + expected_admin_pin_code); +} + +void test_user_credential_admin_pin_code_report_deletion_happy_case() +{ + // Simulate report with 0 as pin code size + uint8_t admin_pin_code_size = 0; + uint8_t expected_operation_result = 0x04; + + // Simulate already present code + auto admin_pin_code_node + = cpp_endpoint_id_node.emplace_node(ATTRIBUTE(ADMIN_PIN_CODE)); + admin_pin_code_node.set_reported(string_to_uint8_vector("1312")); + + // Report frame + zwave_frame report_frame; + uint8_t size_byte = (expected_operation_result << 4) | admin_pin_code_size; + report_frame.add(size_byte); + + helper_test_report_frame(ADMIN_PIN_CODE_REPORT, report_frame); + + // Attribute store test + helper_test_attribute_value(ATTRIBUTE(ADMIN_PIN_CODE_OPERATION_RESULT), + expected_operation_result); + std::vector empty_vector = {0}; + helper_test_attribute_value(ATTRIBUTE(ADMIN_PIN_CODE), empty_vector); +} + +} // extern "C" \ No newline at end of file diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c index d231a8211a..84a5031c06 100644 --- a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c @@ -11,7 +11,7 @@ * *****************************************************************************/ #include "zwave_command_class_zwave_plus_info.h" -#include "zwave_command_class_test_helper.h" +#include "zwave_raw_frame_test_helper.h" // Includes from other components #include "zwave_tx_mock.h" diff --git a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c.rej b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c.rej new file mode 100644 index 0000000000..9e67e79548 --- /dev/null +++ b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c.rej @@ -0,0 +1,10 @@ +diff a/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c b/applications/zpc/components/zwave_command_classes/test/zwave_command_class_zwaveplus_info_test.c (rejected hunks) +@@ -11,7 +11,7 @@ + * + *****************************************************************************/ + #include "zwave_command_class_zwave_plus_info.h" +-#include "zwave_command_class_test_helper.h" ++#include "zwave_raw_frame_test_helper.h" + + // Includes from other components + #include "zwave_tx_mock.h" diff --git a/components/uic_attribute_store/include/attribute.hpp b/components/uic_attribute_store/include/attribute.hpp index 5c0d7b2057..b30947a68b 100644 --- a/components/uic_attribute_store/include/attribute.hpp +++ b/components/uic_attribute_store/include/attribute.hpp @@ -17,7 +17,7 @@ * @ingroup attribute_store * * This file defines a C++ wrapper around the attribute store. Using the wrapper - * will in general make the attribute store access more read able. + * will in general make the attribute store access more readable. * * @{ */ @@ -29,12 +29,15 @@ #include "attribute_store.h" #include "attribute_store_helper.h" +#include "attribute_store_type_registration.h" + #include #include #include #include #include #include +#include // for ostringstream namespace attribute_store { /** @@ -92,7 +95,7 @@ class attribute } /** - * Get the first parrent of a give type. If this node match the type + * Get the first parent of a give type. If this node match the type * this node is returned. * @ref attribute_store_get_first_parent_with_type */ @@ -133,11 +136,12 @@ class attribute uint8_t buffer[ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH]; uint8_t size = 0; if (get(value_type, (uint8_t *)buffer, &size)) { - if constexpr(std::is_same::value) { - return std::string(reinterpret_cast(buffer)); - }else if constexpr (is_iterable::value) { // For iterable containers we copy the data + if constexpr (std::is_same::value) { + return std::string(reinterpret_cast(buffer)); + } else if constexpr ( + is_iterable::value) { // For iterable containers we copy the data typedef typename T::value_type v_t; - //Make sure that value type of the conrainter int,float,bool ... etc + //Make sure that value type of the container int,float,bool ... etc static_assert(std::is_trivially_copyable::value); T v; v_t *start = reinterpret_cast(buffer); @@ -158,14 +162,12 @@ class attribute return *(reinterpret_cast(buffer)); } else { throw std::invalid_argument( - "Unexpected attribute size for node " + std::to_string(_n) - + ".Expected: " + std::to_string(sizeof(T)) - + ", actual: " + std::to_string(size) + "Unexpected attribute size for node " + name_and_id() + ".Expected: " + + std::to_string(sizeof(T)) + ", actual: " + std::to_string(size) + " value state: " + std::to_string(value_type) + "."); } } else { - throw std::invalid_argument("Unable to read attribute " - + std::to_string(_n)); + throw std::invalid_argument("Unable to read attribute " + name_and_id()); } } @@ -178,8 +180,7 @@ class attribute value_type, value, size)) { - throw std::invalid_argument("Unable to write attribute " - + std::to_string(_n)); + throw std::invalid_argument("Unable to write attribute " + name_and_id()); } else { return *this; } @@ -193,22 +194,24 @@ class attribute * value. If the attribute node is invalid an exception will be thrown. * * @tparam T Data type to write - * @param value_type Desired of reported value + * @param value_type Desired or reported value * @param value Value to write */ - template - inline attribute &set(attribute_store_node_value_state_t value_type, const T& value) - { - if constexpr(std::is_same::value) { - // We are storing strings as C Strings with the null termination caracter in the attribute store. - return set(value_type, reinterpret_cast(value), std::strlen(value)+1); - } else if constexpr(std::is_same::value) { - // We are storing strings as C Strings with the null termination caracter in the attribute store. - return set(value_type, value.c_str()); + template inline attribute & + set(attribute_store_node_value_state_t value_type, const T &value) + { + if constexpr (std::is_same::value) { + // We are storing strings as C Strings with the null termination character in the attribute store. + return set(value_type, std::string(value)); + } else if constexpr (std::is_same::value) { + // We are storing strings as C Strings with the null termination character in the attribute store. + return set(value_type, + reinterpret_cast(value.c_str()), + value.size() + 1); } else if constexpr (is_iterable::value) { typedef typename T::value_type v_t; - //Make sure that value type of the conrainter int,float,bool ... etc + //Make sure that value type of the container int,float,bool ... etc static_assert(std::is_trivially_copyable::value); //The purpose of this is to convert the iterable container into a linear buffer @@ -217,14 +220,14 @@ class attribute return set(value_type, reinterpret_cast(v.data()), v.size() * sizeof(v_t)); - } - else { + } else { static_assert(std::is_trivially_copyable::value); - return set(value_type, reinterpret_cast(&value), sizeof(T)); + return set(value_type, + reinterpret_cast(&value), + sizeof(T)); } } - inline void clear(attribute_store_node_value_state_t value_type) { if (SL_STATUS_OK @@ -234,7 +237,7 @@ class attribute } /** - * @brief Helper to read the repported value + * @brief Helper to read the reported value */ template T reported() const { @@ -248,21 +251,26 @@ class attribute return get(DESIRED_ATTRIBUTE); } + bool exists(attribute_store_node_value_state_t state) const + { + return attribute_store_is_value_defined(_n, state); + } + /** * @brief Returns true if this attribute has a desired value */ - bool desired_exists() + bool desired_exists() const { - return attribute_store_is_value_defined(_n, DESIRED_ATTRIBUTE); + return exists(DESIRED_ATTRIBUTE); } /** * @brief Returns true if this attribute has a reported value */ - bool reported_exists() + bool reported_exists() const { - return attribute_store_is_value_defined(_n, REPORTED_ATTRIBUTE); + return exists(REPORTED_ATTRIBUTE); } template T desired_or_reported() @@ -281,7 +289,7 @@ class attribute } /** - * @brief Helper to write the repported value + * @brief Helper to write the reported value */ template attribute &set_reported(T v) { @@ -363,13 +371,13 @@ class attribute } /** - * @brief Get child by value + * @brief Get child by value (reported value) * - * Get a child by the reppored value of that child. If no matching child is + * Get a child by the reported value of that child. If no matching child is * found an invalid node is returned. * * @tparam T Type of value - * @param type Desired of repported + * @param type Attribute store type * @param value The value to search for * @return attribute */ @@ -384,6 +392,31 @@ class attribute return ATTRIBUTE_STORE_INVALID_NODE; } + /** + * @brief Get child by value and state + * + * Get a child by the given state of that child. If no matching child is + * found an invalid node is returned. + * + * @tparam T Type of value + * @param type Attribute store type + * @param value The value to search for + * @param value_type The value state + * @return attribute + */ + template attribute + child_by_type_and_value(attribute_store_type_t type, + T value, + attribute_store_node_value_state_t value_type) const + { + for (auto c: children(type)) { + if (c.exists(value_type) && c.get(value_type) == value) { + return c; + } + } + return ATTRIBUTE_STORE_INVALID_NODE; + } + /** * @brief Checks if this node is valid * @@ -424,25 +457,28 @@ class attribute } /** - * @brief Get or add a child of a given attribtue type and value. + * @brief Get or add a child of a given attribute type and value. * * This function will check if this nodes as a child of a given type and value. * If a child exists the child is returned, if it does not exist the child is - * created and the repported value is set. + * created and the reported value is set. */ template - attribute emplace_node(attribute_store_type_t type, T val) + attribute emplace_node(attribute_store_type_t type, + T val, + attribute_store_node_value_state_t value_state + = REPORTED_ATTRIBUTE) { - attribute a = child_by_type_and_value(type, val); + attribute a = child_by_type_and_value(type, val, value_state); if (a.is_valid()) { return a; } else { - return add_node(type).set_reported(val); + return add_node(type).set(value_state, val); } } /** - * @brief Get or add a child of a given attribtue type. + * @brief Get or add a child of a given attribute type. * * This function will check if this nodes as a child of a given type. * If a child exists the child is returned, if it does not exist the child is @@ -468,6 +504,11 @@ class attribute _n = ATTRIBUTE_STORE_INVALID_NODE; } + sl_status_t change_parent(attribute new_parent) + { + return attribute_store_change_parent(this->_n, new_parent); + } + /** * @brief Visit all nodes in the tree. * @@ -495,6 +536,62 @@ class attribute return status; } + std::string name() const + { + return attribute_store_get_type_name(this->type()); + } + + std::string name_and_id() const + { + std::ostringstream out; + out << name() << " (Node " << _n << ")"; + return out.str(); + } + + + std::string value_to_string() const + { + + std::string str_value; + try { + switch (attribute_store_get_storage_type(this->type())) { + case UNKNOWN_STORAGE_TYPE: + case EMPTY_STORAGE_TYPE: + case FIXED_SIZE_STRUCT_STORAGE_TYPE: + case INVALID_STORAGE_TYPE: + return "Not displayable value for " + name_and_id(); + case U8_STORAGE_TYPE: + case U16_STORAGE_TYPE: + case U32_STORAGE_TYPE: + case U64_STORAGE_TYPE: + str_value = _get_str_value(); + break; + case I8_STORAGE_TYPE: + case I16_STORAGE_TYPE: + case I32_STORAGE_TYPE: + case I64_STORAGE_TYPE: + str_value = _get_str_value(); + break; + case FLOAT_STORAGE_TYPE: + case DOUBLE_STORAGE_TYPE: + str_value = _get_str_value(); + break; + case C_STRING_STORAGE_TYPE: + str_value = _get_str_value(); + break; + case BYTE_ARRAY_STORAGE_TYPE: + str_value = _get_str_value>(); + break; + default: + return "Unkown value type for " + name_and_id(); + } + } catch (...) { + return "Can't get values of " + name_and_id(); + } + + return name_and_id() + " values : " + str_value; + } + //type conversion back to attribute_store_node_t operator attribute_store_node_t() const { @@ -513,6 +610,40 @@ class attribute private: attribute_store_node_t _n = ATTRIBUTE_STORE_INVALID_NODE; + + template + std::string _get_str_value() const { + auto desired_value = _get_str_value_with_state(DESIRED_ATTRIBUTE); + auto reported_value = _get_str_value_with_state(REPORTED_ATTRIBUTE); + + return reported_value + " (" + desired_value + ")"; + } + + template + std::string _get_str_value_with_state(attribute_store_node_value_state_t state) const { + if (!exists(state)) { + return "<>"; + } + + std::string str_value = ""; + + if constexpr (std::is_same>::value) { + str_value = "["; + for (uint8_t byte: get>(state)) { + str_value += std::to_string(byte) + ","; + } + str_value.pop_back(); + str_value += "]"; + } else if constexpr (std::is_same::value + || std::is_same::value + || std::is_same::value) { + str_value = std::to_string(get(state)); + } else if constexpr (std::is_same::value) { + str_value = get(state); + } + + return str_value; + } }; } // namespace attribute_store diff --git a/components/uic_attribute_store/include/attribute_store.h b/components/uic_attribute_store/include/attribute_store.h index 59dfe10db7..288999918e 100644 --- a/components/uic_attribute_store/include/attribute_store.h +++ b/components/uic_attribute_store/include/attribute_store.h @@ -505,6 +505,20 @@ uint8_t attribute_store_get_node_value_size( sl_status_t attribute_store_refresh_node_and_children_callbacks( attribute_store_node_t node); +/** + * @brief Change parent of node to the new parent. + * + * @note The parent node must be a valid node in the attribute store. + * @note The new parent should have the type than the node current parent + * + * @param node The node handle of the node to change parent + * @param new_parent The node handle of the new parent + * + * @return SL_STATUS_OK if the parent was changed successfully, SL_STATUS_FAIL otherwise + */ +sl_status_t attribute_store_change_parent(attribute_store_node_t node, + attribute_store_node_t new_parent); + /** * @brief Log the content of the Attribute Store tree using \ref sl_log. */ diff --git a/components/uic_attribute_store/src/attribute_store.cpp b/components/uic_attribute_store/src/attribute_store.cpp index ed5a6a333a..043141d875 100644 --- a/components/uic_attribute_store/src/attribute_store.cpp +++ b/components/uic_attribute_store/src/attribute_store.cpp @@ -158,6 +158,27 @@ static attribute_store_node * return found_node; } +sl_status_t attribute_store_change_parent(attribute_store_node_t node, + attribute_store_node_t new_parent) +{ + auto base_node = attribute_store_get_node_from_id(node); + if (base_node == NULL) { + sl_log_error(LOG_TAG, "Node %d not found in the attribute store.", node); + return SL_STATUS_FAIL; + } + auto parent_node = attribute_store_get_node_from_id(new_parent); + if (parent_node == NULL) { + sl_log_error(LOG_TAG, + "Parent node %d not found in the attribute store.", + new_parent); + return SL_STATUS_FAIL; + } + + return base_node->change_parent(parent_node) != NULL ? SL_STATUS_OK + : SL_STATUS_FAIL; +} + + /** * @brief Compares if a node value is identical to the value/value size * diff --git a/components/uic_attribute_store/src/attribute_store_node.cpp b/components/uic_attribute_store/src/attribute_store_node.cpp index de96b58a30..3610a8f2e4 100644 --- a/components/uic_attribute_store/src/attribute_store_node.cpp +++ b/components/uic_attribute_store/src/attribute_store_node.cpp @@ -93,6 +93,40 @@ attribute_store_node *attribute_store_node::find_id(attribute_store_node_t _id) return NULL; } +attribute_store_node* + attribute_store_node::change_parent(attribute_store_node* new_parent) +{ + if (this->parent_node == NULL) { + sl_log_critical(LOG_TAG, "Cannot change parent of the root node."); + return NULL; + } + + if (new_parent == NULL) { + sl_log_warning(LOG_TAG, "Cannot change parent to a NULL node."); + return NULL; + } + + if (new_parent == this->parent_node) { + sl_log_warning(LOG_TAG, "Cannot change parent to the same node."); + return NULL; + } + + if (new_parent->type != this->parent_node->type) { + sl_log_warning(LOG_TAG, + "Cannot change parent to a node of different type. " + "New Parent type: %s, Old parent type: %s", + attribute_store_get_type_name(new_parent->type), + attribute_store_get_type_name(this->parent_node->type)); + return NULL; + } + // Clear old parent child link + this->parent_node->remove_child_link(this); + + new_parent->child_nodes.push_back(this); + this->parent_node = new_parent; + return new_parent; +} + /////////////////////////////////////////////////////////////////////////////// // Log functions /////////////////////////////////////////////////////////////////////////////// diff --git a/components/uic_attribute_store/src/attribute_store_node.h b/components/uic_attribute_store/src/attribute_store_node.h index c840746904..63d0a2b247 100644 --- a/components/uic_attribute_store/src/attribute_store_node.h +++ b/components/uic_attribute_store/src/attribute_store_node.h @@ -109,6 +109,17 @@ class attribute_store_node */ attribute_store_node *find_id(attribute_store_node_t _id); + /** + * @brief Change the parent node to new_parent + * + * @note The new parent must be of the same type as the current parent + * + * @param new_parent The new parent node to assign to the current node + * + * @returns The new parent node if the operation was successful, NULL otherwise + */ + attribute_store_node *change_parent(attribute_store_node* new_parent); + /** * @brief Logs the content of the a Node using \ref sl_log */ diff --git a/components/uic_attribute_store/test/attribute_store_cpp_wrap_test.cpp b/components/uic_attribute_store/test/attribute_store_cpp_wrap_test.cpp index e5cbecf405..dcdccacbed 100644 --- a/components/uic_attribute_store/test/attribute_store_cpp_wrap_test.cpp +++ b/components/uic_attribute_store/test/attribute_store_cpp_wrap_test.cpp @@ -150,13 +150,37 @@ void test_attribute_store_cpp_wrap_navigation_test() attribute n3 = d.add_node(0x42); n1.set_reported(0); + n1.set_desired(3); + n2.set_reported(1); + n2.set_desired(4); + n3.set_reported(2); for (int i = 0; i < 3; i++) { TEST_ASSERT_EQUAL(i, d.child_by_type(0x42, i).reported()); } - TEST_ASSERT_TRUE(n3 == d.child_by_type_and_value(0x42, 2)); + + + TEST_ASSERT_EQUAL(n3, d.child_by_type_and_value(0x42, 2)); + TEST_ASSERT_EQUAL( + n3, d.child_by_type_and_value(0x42, 2, REPORTED_ATTRIBUTE)); + TEST_ASSERT_EQUAL( + n2, d.child_by_type_and_value(0x42, 4, DESIRED_ATTRIBUTE)); + TEST_ASSERT_EQUAL( + n1, d.child_by_type_and_value(0x42, 3, DESIRED_OR_REPORTED_ATTRIBUTE)); + TEST_ASSERT_EQUAL( + n3, + d.child_by_type_and_value(0x42, 2, DESIRED_OR_REPORTED_ATTRIBUTE)); + + // DESIRED_OR_REPORTED_ATTRIBUTE checks for desired value if defined, otherwise takes reported. + // Since n2 have it's desired value set to 4, it will not be returned here. + TEST_ASSERT_EQUAL( + ATTRIBUTE_STORE_INVALID_NODE, + d.child_by_type_and_value(0x42, 1, DESIRED_OR_REPORTED_ATTRIBUTE)); + TEST_ASSERT_EQUAL( + ATTRIBUTE_STORE_INVALID_NODE, + d.child_by_type_and_value(0x42, 5, DESIRED_ATTRIBUTE)); } void test_attribute_store_cpp_wrap_strings() @@ -192,4 +216,144 @@ void test_attribute_store_cpp_wrap_strings() ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH); TEST_ASSERT_EQUAL_STRING("my new string value", read_string); } + +void test_attribute_store_cpp_wrap_emplace_happy_case() +{ + constexpr attribute_store_type_t node_id = 0x42; + + auto root = attribute::root(); + auto node = root.add_node(node_id); + + node.set_reported(12); + + TEST_ASSERT_EQUAL_MESSAGE(node, + root.emplace_node(node_id, 12), + "Should not create a new node"); + + TEST_ASSERT_EQUAL_MESSAGE(node + 1, + root.emplace_node(node_id, 13), + "Should have created a new node"); + + node.set_desired(15); + + + TEST_ASSERT_EQUAL_MESSAGE(node, + root.emplace_node(node_id, 15, DESIRED_ATTRIBUTE), + "Should not create a new node"); + + TEST_ASSERT_EQUAL_MESSAGE(node + 2, + root.emplace_node(node_id, 16, DESIRED_ATTRIBUTE), + "Should have created a new node"); } + +void test_attribute_store_change_parent_happy_case() +{ + /* A + * / \ + * B B + * / \ + * C D +*/ + + attribute a = attribute::root().add_node('A'); + attribute b1 = a.add_node('B'); + attribute b2 = a.add_node('B'); + attribute c = b1.add_node('C'); + attribute d = b1.add_node('D'); + + c.set_reported(55); + d.set_reported(42); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_OK, d.change_parent(b2), "Change parent should have worked"); + + TEST_ASSERT_EQUAL_MESSAGE(1, b1.child_count(), "B1 should only have 1 child now"); + TEST_ASSERT_EQUAL_MESSAGE(1, b2.child_count(), "B2 should have 1 child now"); + TEST_ASSERT_EQUAL_MESSAGE(d, b2.child(0), "D should be the only child of B2"); + TEST_ASSERT_EQUAL_MESSAGE(d.parent(), b2, "D should have B2 as parent"); + TEST_ASSERT_EQUAL_MESSAGE(42, + d.reported(), + "D should have 42 as reported value"); +} + +void test_attribute_store_change_parent_not_same_parent_type() +{ + /* A + * / \ + * B E + * / \ + * C D +*/ + + attribute a = attribute::root().add_node('A'); + attribute b = a.add_node('B'); + attribute e = a.add_node('E'); + attribute c = b.add_node('C'); + attribute d = b.add_node('D'); + + c.set_reported(55); + d.set_reported(42); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + d.change_parent(e), + "Change parent should NOT have worked"); + + TEST_ASSERT_EQUAL_MESSAGE(2, b.child_count(), "B should still have 2 child"); + TEST_ASSERT_EQUAL_MESSAGE(0, e.child_count(), "E should not have any child"); + TEST_ASSERT_EQUAL_MESSAGE(d.parent(), b, "D should have B as parent"); + TEST_ASSERT_EQUAL_MESSAGE(42, + d.reported(), + "D should have 42 as reported value"); +} + + +void test_attribute_store_change_parent_not_same_parent() +{ + /* A + * / \ + * B E + * / \ + * C D +*/ + + attribute a = attribute::root().add_node('A'); + attribute b = a.add_node('B'); + attribute e = a.add_node('E'); + attribute c = b.add_node('C'); + attribute d = b.add_node('D'); + + c.set_reported(55); + d.set_reported(42); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + d.change_parent(b), + "Change parent should NOT have worked"); + + TEST_ASSERT_EQUAL_MESSAGE(2, b.child_count(), "B should still have 2 child"); + TEST_ASSERT_EQUAL_MESSAGE(0, e.child_count(), "E should not have any child"); + TEST_ASSERT_EQUAL_MESSAGE(d.parent(), b, "D should have B as parent"); + TEST_ASSERT_EQUAL_MESSAGE(42, + d.reported(), + "D should have 42 as reported value"); +} + +void test_attribute_store_change_parent_invalids() +{ + attribute root = attribute::root(); + attribute a = root.add_node('A'); + + TEST_ASSERT_EQUAL_MESSAGE(SL_STATUS_FAIL, + root.change_parent(a), + "Shouldn't be able to change root node parent"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + a.change_parent(attribute(0)), + "Shouldn't be able to change parent to a invalid node parent"); + + TEST_ASSERT_EQUAL_MESSAGE( + SL_STATUS_FAIL, + attribute(0).change_parent(a), + "Shouldn't be able to change a invalid node parent"); +} + +} // extern "C" diff --git a/components/uic_dotdot/dotdot-xml/Unify_UserCredential.xml b/components/uic_dotdot/dotdot-xml/Unify_UserCredential.xml new file mode 100644 index 0000000000..da1327a851 --- /dev/null +++ b/components/uic_dotdot/dotdot-xml/Unify_UserCredential.xml @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/uic_dotdot/dotdot-xml/library.xml b/components/uic_dotdot/dotdot-xml/library.xml index 334f0b1c99..e4f18db497 100644 --- a/components/uic_dotdot/dotdot-xml/library.xml +++ b/components/uic_dotdot/dotdot-xml/library.xml @@ -493,4 +493,6 @@ applicable to this document can be found in the LICENSE.md file. + + \ No newline at end of file diff --git a/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h index a988971041..b1512d6a82 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_attribute_id_definitions.h @@ -831,6 +831,15 @@ typedef enum { #define DOTDOT_NAME_AND_LOCATION_LOCATION_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x1) // Definitions for cluster: ConfigurationParameters #define DOTDOT_CONFIGURATION_PARAMETERS_CONFIGURATION_PARAMETERS_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x0) +// Definitions for cluster: UserCredential +#define DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x0) +#define DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x1) +#define DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x2) +#define DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_TYPES_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x3) +#define DOTDOT_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x4) +#define DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x5) +#define DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x6) +#define DOTDOT_USER_CREDENTIAL_ADMIN_PIN_CODE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x7) // Definitions for cluster: AoXLocator #define DOTDOT_AOX_LOCATOR_REPORTING_MODE_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x1) #define DOTDOT_AOX_LOCATOR_POSITION_AND_ORIENTATION_VALID_ATTRIBUTE_ID ((dotdot_attribute_id_t)0x2) diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h index a49fb8fcb9..ac5af9c945 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_command_id_definitions.h @@ -352,6 +352,28 @@ #define DOTDOT_CONFIGURATION_PARAMETERS_SET_PARAMETER_COMMAND_ID (0x3) #define DOTDOT_CONFIGURATION_PARAMETERS_DISCOVER_PARAMETER_RANGE_COMMAND_ID (0x4) +// Commands for cluster: UserCredential +#define DOTDOT_USER_CREDENTIAL_ADD_USER_COMMAND_ID (0x1) +#define DOTDOT_USER_CREDENTIAL_MODIFY_USER_COMMAND_ID (0x2) +#define DOTDOT_USER_CREDENTIAL_DELETE_USER_COMMAND_ID (0x3) +#define DOTDOT_USER_CREDENTIAL_ADD_CREDENTIAL_COMMAND_ID (0x4) +#define DOTDOT_USER_CREDENTIAL_MODIFY_CREDENTIAL_COMMAND_ID (0x5) +#define DOTDOT_USER_CREDENTIAL_DELETE_CREDENTIAL_COMMAND_ID (0x6) +#define DOTDOT_USER_CREDENTIAL_DELETE_ALL_USERS_COMMAND_ID (0x7) +#define DOTDOT_USER_CREDENTIAL_DELETE_ALL_CREDENTIALS_COMMAND_ID (0x8) +#define DOTDOT_USER_CREDENTIAL_DELETE_ALL_CREDENTIALS_BY_TYPE_COMMAND_ID (0x9) +#define DOTDOT_USER_CREDENTIAL_DELETE_ALL_CREDENTIALS_FOR_USER_COMMAND_ID (0xA) +#define DOTDOT_USER_CREDENTIAL_DELETE_ALL_CREDENTIALS_FOR_USER_BY_TYPE_COMMAND_ID (0xB) +#define DOTDOT_USER_CREDENTIAL_CREDENTIAL_LEARN_START_ADD_COMMAND_ID (0xC) +#define DOTDOT_USER_CREDENTIAL_CREDENTIAL_LEARN_START_MODIFY_COMMAND_ID (0xD) +#define DOTDOT_USER_CREDENTIAL_CREDENTIAL_LEARN_STOP_COMMAND_ID (0xE) +#define DOTDOT_USER_CREDENTIAL_CREDENTIAL_ASSOCIATION_COMMAND_ID (0xF) +#define DOTDOT_USER_CREDENTIAL_GET_USER_CHECKSUM_COMMAND_ID (0x10) +#define DOTDOT_USER_CREDENTIAL_GET_CREDENTIAL_CHECKSUM_COMMAND_ID (0x11) +#define DOTDOT_USER_CREDENTIAL_GET_ALL_USERS_CHECKSUM_COMMAND_ID (0x12) +#define DOTDOT_USER_CREDENTIAL_SET_ADMIN_PIN_CODE_COMMAND_ID (0x13) +#define DOTDOT_USER_CREDENTIAL_DEACTIVATE_ADMIN_PIN_CODE_COMMAND_ID (0x14) + // Commands for cluster: AoXLocator #define DOTDOT_AOX_LOCATOR_IQ_REPORT_COMMAND_ID (0x1) #define DOTDOT_AOX_LOCATOR_ANGLE_REPORT_COMMAND_ID (0x2) diff --git a/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h b/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h index 34db7d7b79..ee7d429b0f 100644 --- a/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h +++ b/components/uic_dotdot/zap-generated/include/dotdot_cluster_id_definitions.h @@ -238,6 +238,10 @@ #define DOTDOT_CONFIGURATION_PARAMETERS_CLUSTER_ID ((dotdot_cluster_id_t)0xFD07) +// Definitions for cluster: UserCredential +#define DOTDOT_USER_CREDENTIAL_CLUSTER_ID ((dotdot_cluster_id_t)0xFD08) + + // Definitions for cluster: AoXLocator #define DOTDOT_AOX_LOCATOR_CLUSTER_ID ((dotdot_cluster_id_t)0xFD10) diff --git a/components/uic_dotdot/zap-generated/include/zap-types.h b/components/uic_dotdot/zap-generated/include/zap-types.h index 21b04b1420..e8705b4de7 100644 --- a/components/uic_dotdot/zap-generated/include/zap-types.h +++ b/components/uic_dotdot/zap-generated/include/zap-types.h @@ -500,6 +500,28 @@ typedef enum { ZCL_COMMISSIONING_STARTUP_CONTROL_JOIN_USING_MAC_ASSOCIATION = 3, } CommissioningStartupControl; +// Enum for CredRule +typedef enum { + ZCL_CRED_RULE_SINGLE = 1, + ZCL_CRED_RULE_DUAL = 2, + ZCL_CRED_RULE_TRIPLE = 3, +} CredRule; + +// Enum for CredType +typedef enum { + ZCL_CRED_TYPE_PIN_CODE = 1, + ZCL_CRED_TYPE_PASSWORD = 2, + ZCL_CRED_TYPE_RFID_CODE = 3, + ZCL_CRED_TYPE_BLE = 4, + ZCL_CRED_TYPE_NFC = 5, + ZCL_CRED_TYPE_UWB = 6, + ZCL_CRED_TYPE_EYE_BIOMETRIC = 7, + ZCL_CRED_TYPE_FACE_BIOMETRIC = 8, + ZCL_CRED_TYPE_FINGER_BIOMETRIC = 9, + ZCL_CRED_TYPE_HAND_BIOMETRIC = 10, + ZCL_CRED_TYPE_UNSPECIFIED_BIOMETRIC = 11, +} CredType; + // Enum for CredentialRuleEnum typedef enum { ZCL_CREDENTIAL_RULE_ENUM_SINGLE = 0, @@ -1341,6 +1363,33 @@ typedef enum { ZCL_UNIFY_THERMOSTAT_THERMOSTAT_MODE_MANUFACTURER_SPECIFIC = 31, } UnifyThermostatThermostatMode; +// Enum for UserModifierType +typedef enum { + ZCL_USER_MODIFIER_TYPE_DNE = 0, + ZCL_USER_MODIFIER_TYPE_UNKNOWN = 1, + ZCL_USER_MODIFIER_TYPE_Z_WAVE = 2, + ZCL_USER_MODIFIER_TYPE_LOCALLY = 3, + ZCL_USER_MODIFIER_TYPE_MOBILE_APP_OR_OTHER_IO_T = 4, +} UserModifierType; + +// Enum for UserNameEncodingType +typedef enum { + ZCL_USER_NAME_ENCODING_TYPE_ASCII = 0, + ZCL_USER_NAME_ENCODING_TYPE_OEM_EXTENDED_ASCII = 1, + ZCL_USER_NAME_ENCODING_TYPE_UTF_16 = 2, +} UserNameEncodingType; + +// Enum for UserTypeEnum +typedef enum { + ZCL_USER_TYPE_ENUM_GENERAL_USER = 0, + ZCL_USER_TYPE_ENUM_PROGRAMMING_USER = 3, + ZCL_USER_TYPE_ENUM_NON_ACCESS_USER = 4, + ZCL_USER_TYPE_ENUM_DURESS_USER = 5, + ZCL_USER_TYPE_ENUM_DISPOSABLE_USER = 6, + ZCL_USER_TYPE_ENUM_EXPIRING_USER = 7, + ZCL_USER_TYPE_ENUM_REMOTE_ONLY_USER = 9, +} UserTypeEnum; + // Enum for WindowCoveringWindowCoveringType typedef enum { ZCL_WINDOW_COVERING_WINDOW_COVERING_TYPE_ROLLERSHADE = 0, @@ -2121,6 +2170,48 @@ typedef enum { #define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_FULL_POWER_OFFSET (14) #define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_MANUFACTURER_SPECIFIC (32768) #define UNIFY_THERMOSTAT_SUPPORTED_THERMOSTAT_MODE_MANUFACTURER_SPECIFIC_OFFSET (15) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_SINGLE (2) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_SINGLE_OFFSET (1) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_DUAL (4) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_DUAL_OFFSET (2) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_TRIPLE (8) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_TRIPLE_OFFSET (3) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_PIN_CODE (1) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_PIN_CODE_OFFSET (0) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_PASSWORD (2) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_PASSWORD_OFFSET (1) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_RFID_CODE (4) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_RFID_CODE_OFFSET (2) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_BLE (8) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_BLE_OFFSET (3) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_NFC (16) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_NFC_OFFSET (4) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_UWB (32) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_UWB_OFFSET (5) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_EYE_BIOMETRIC (64) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_EYE_BIOMETRIC_OFFSET (6) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_FACE_BIOMETRIC (128) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_FACE_BIOMETRIC_OFFSET (7) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_FINGER_BIOMETRIC (256) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_FINGER_BIOMETRIC_OFFSET (8) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_HAND_BIOMETRIC (512) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_HAND_BIOMETRIC_OFFSET (9) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_UNSPECIFIED_BIOMETRIC (1024) +#define USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_UNSPECIFIED_BIOMETRIC_OFFSET (10) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_GENERAL_USER (1) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_GENERAL_USER_OFFSET (0) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_PROGRAMMING_USER (8) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_PROGRAMMING_USER_OFFSET (3) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_NON_ACCESS_USER (16) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_NON_ACCESS_USER_OFFSET (4) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_DURESS_USER (32) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_DURESS_USER_OFFSET (5) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_DISPOSABLE_USER (64) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_DISPOSABLE_USER_OFFSET (6) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_EXPIRING_USER (128) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_EXPIRING_USER_OFFSET (7) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_REMOTE_ONLY_USER (512) +#define USER_CREDENTIAL_SUPPORTED_USER_TYPES_REMOTE_ONLY_USER_OFFSET (9) #define WINDOW_COVERING_CONFIG_OR_STATUS_OPERATIONAL (1) #define WINDOW_COVERING_CONFIG_OR_STATUS_OPERATIONAL_OFFSET (0) #define WINDOW_COVERING_CONFIG_OR_STATUS_ONLINE (2) diff --git a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md index 3fd2a67fc1..8c3bd65b46 100644 --- a/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md +++ b/components/uic_dotdot/zap-generated/readme_ucl_mqtt_reference.md @@ -51843,6 +51843,1571 @@ mosquitto_pub -t 'ucl/by-unid///ConfigurationParameters/Commands/Force


+ + + + + +\page user_credential UserCredential Cluster +The following commands and attributes are accepted as JSON payloads for the +UserCredential cluster. + +

+ + + + +\section user_credential_attrs UserCredential Attributes +The following attribute topics are used to retrieve the UserCredential cluster state. + +
+ +\subsection user_credential_attr_supported_user_unique_identifiers UserCredential/SupportedUserUniqueIdentifiers Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportedUserUniqueIdentifiers/Reported +[PREFIX]/UserCredential/Attributes/SupportedUserUniqueIdentifiers/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportedUserUniqueIdentifiers Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "integer" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportedUserUniqueIdentifiers attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportedUserUniqueIdentifiers/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportedUserUniqueIdentifiers/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportedUserUniqueIdentifiers/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_supported_credential_rules UserCredential/SupportedCredentialRules Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportedCredentialRules/Reported +[PREFIX]/UserCredential/Attributes/SupportedCredentialRules/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportedCredentialRules Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "UserCredentialSupportedCredentialRules" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportedCredentialRules attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportedCredentialRules/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportedCredentialRules/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportedCredentialRules/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_supported_credential_types UserCredential/SupportedCredentialTypes Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportedCredentialTypes/Reported +[PREFIX]/UserCredential/Attributes/SupportedCredentialTypes/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportedCredentialTypes Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "UserCredentialSupportedCredentialTypes" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportedCredentialTypes attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportedCredentialTypes/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportedCredentialTypes/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportedCredentialTypes/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_supported_user_types UserCredential/SupportedUserTypes Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportedUserTypes/Reported +[PREFIX]/UserCredential/Attributes/SupportedUserTypes/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportedUserTypes Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "UserCredentialSupportedUserTypes" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportedUserTypes attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportedUserTypes/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportedUserTypes/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportedUserTypes/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_support_credential_checksum UserCredential/SupportCredentialChecksum Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportCredentialChecksum/Reported +[PREFIX]/UserCredential/Attributes/SupportCredentialChecksum/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportCredentialChecksum Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportCredentialChecksum attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportCredentialChecksum/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportCredentialChecksum/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportCredentialChecksum/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_support_admin_pin_code UserCredential/SupportAdminPinCode Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportAdminPinCode/Reported +[PREFIX]/UserCredential/Attributes/SupportAdminPinCode/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportAdminPinCode Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportAdminPinCode attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportAdminPinCode/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportAdminPinCode/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportAdminPinCode/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_support_admin_pin_code_deactivation UserCredential/SupportAdminPinCodeDeactivation Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/SupportAdminPinCodeDeactivation/Reported +[PREFIX]/UserCredential/Attributes/SupportAdminPinCodeDeactivation/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SupportAdminPinCodeDeactivation Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "boolean" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for SupportAdminPinCodeDeactivation attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/SupportAdminPinCodeDeactivation/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/SupportAdminPinCodeDeactivation/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/SupportAdminPinCodeDeactivation/Reported { "value": } + +``` + +

+ +\subsection user_credential_attr_admin_pin_code UserCredential/AdminPinCode Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/AdminPinCode/Reported +[PREFIX]/UserCredential/Attributes/AdminPinCode/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster AdminPinCode Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] +} +``` + + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for AdminPinCode attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid/+/+/UserCredential/Attributes/AdminPinCode/+' + +# Example output + +ucl/by-unid//ep0/UserCredential/Attributes/AdminPinCode/Desired { "value": } +ucl/by-unid//ep0/UserCredential/Attributes/AdminPinCode/Reported { "value": } + +``` + +

+ + +\subsection user_credential_attr_cluster_revision UserCredential/ClusterRevision Attribute + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Attributes/ClusterRevision/Reported +[PREFIX]/UserCredential/Attributes/ClusterRevision/Desired +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster ClusterRevision Attribute Properties", + "type": "object", + "properties": { + "value": { + "type": "integer" + } + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To see desired/reported value for ClusterRevision attribute under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/Attributes/ClusterRevision/+' +# Example output +ucl/by-unid///UserCredential/Attributes/ClusterRevision/Desired { "value": } +ucl/by-unid///UserCredential/Attributes/ClusterRevision/Reported { "value": } +``` + + + + + +

+ + + + +\section user_credential_recv_cmd_support UserCredential Command Support + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/SupportedCommands +[PREFIX]/UserCredential/SupportedGeneratedCommands +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Command Support Properties", + "type": "object", + "properties": { + "value": { + "type": "array", + "items" : { + "type": "string", + "enum": [ + "AddUser", + "ModifyUser", + "DeleteUser", + "AddCredential", + "ModifyCredential", + "DeleteCredential", + "DeleteAllUsers", + "DeleteAllCredentials", + "DeleteAllCredentialsByType", + "DeleteAllCredentialsForUser", + "DeleteAllCredentialsForUserByType", + "CredentialLearnStartAdd", + "CredentialLearnStartModify", + "CredentialLearnStop", + "CredentialAssociation", + "GetUserChecksum", + "GetCredentialChecksum", + "GetAllUsersChecksum", + "SetAdminPINCode", + "DeactivateAdminPINCode", + "WriteAttributes", + "ForceReadAttributes" + ] + } + } + } + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To see supported commands for UserCredential cluster under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/SupportedCommands' +# Example output +ucl/by-unid///UserCredential/SupportedCommands { "value": ["AddUser","ModifyUser","DeleteUser","AddCredential","ModifyCredential","DeleteCredential","DeleteAllUsers","DeleteAllCredentials","DeleteAllCredentialsByType","DeleteAllCredentialsForUser","DeleteAllCredentialsForUserByType","CredentialLearnStartAdd","CredentialLearnStartModify","CredentialLearnStop","CredentialAssociation","GetUserChecksum","GetCredentialChecksum","GetAllUsersChecksum","SetAdminPINCode","DeactivateAdminPINCode","WriteAttributes", "ForceReadAttributes"] } +``` + +To see supported generated commands for UserCredential cluster under the by-unid topic space: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/SupportedGeneratedCommands' +# Example output +ucl/by-unid///UserCredential/SupportedGeneratedCommands { "value": [] } +``` + + + + + +

+ + + + +\section user_credential_cmds UserCredential Commands + +

+ +\subsection user_credential_add_user_cmd UserCredential/AddUser Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/AddUser +[PREFIX]/UserCredential/GeneratedCommands/AddUser +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster AddUser Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "UserType": { + "type": "UserTypeEnum" + }, + "UserActiveState": { + "type": "boolean" + }, + "CredentialRule": { + "type": "CredRule" + }, + "UserName": { + "type": "string" + }, + "ExpiringTimeoutMinutes": { + "type": "integer" + }, + "UserNameEncoding": { + "type": "UserNameEncodingType" + } + }, + "required": [ + "UserUniqueID", + "UserType", + "UserActiveState", + "CredentialRule", + "UserName", + "ExpiringTimeoutMinutes", + "UserNameEncoding" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/AddUser command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/AddUser' -m '{ "UserUniqueID": ,"UserType": ,"UserActiveState": ,"CredentialRule": ,"UserName": ,"ExpiringTimeoutMinutes": ,"UserNameEncoding": }' +``` + +To receive a UserCredential/AddUser generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/AddUser' +``` + +

+ +\subsection user_credential_modify_user_cmd UserCredential/ModifyUser Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/ModifyUser +[PREFIX]/UserCredential/GeneratedCommands/ModifyUser +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster ModifyUser Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "UserType": { + "type": "UserTypeEnum" + }, + "UserActiveState": { + "type": "boolean" + }, + "CredentialRule": { + "type": "CredRule" + }, + "UserName": { + "type": "string" + }, + "ExpiringTimeoutMinutes": { + "type": "integer" + }, + "UserNameEncoding": { + "type": "UserNameEncodingType" + } + }, + "required": [ + "UserUniqueID", + "UserType", + "UserActiveState", + "CredentialRule", + "UserName", + "ExpiringTimeoutMinutes", + "UserNameEncoding" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/ModifyUser command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/ModifyUser' -m '{ "UserUniqueID": ,"UserType": ,"UserActiveState": ,"CredentialRule": ,"UserName": ,"ExpiringTimeoutMinutes": ,"UserNameEncoding": }' +``` + +To receive a UserCredential/ModifyUser generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/ModifyUser' +``` + +

+ +\subsection user_credential_delete_user_cmd UserCredential/DeleteUser Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteUser +[PREFIX]/UserCredential/GeneratedCommands/DeleteUser +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteUser Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + } + }, + "required": [ + "UserUniqueID" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteUser command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteUser' -m '{ "UserUniqueID": }' +``` + +To receive a UserCredential/DeleteUser generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteUser' +``` + +

+ +\subsection user_credential_add_credential_cmd UserCredential/AddCredential Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/AddCredential +[PREFIX]/UserCredential/GeneratedCommands/AddCredential +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster AddCredential Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "CredentialType": { + "type": "CredType" + }, + "CredentialSlot": { + "type": "integer" + }, + "CredentialData": { + "type": "string" + } + }, + "required": [ + "UserUniqueID", + "CredentialType", + "CredentialSlot", + "CredentialData" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/AddCredential command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/AddCredential' -m '{ "UserUniqueID": ,"CredentialType": ,"CredentialSlot": ,"CredentialData": }' +``` + +To receive a UserCredential/AddCredential generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/AddCredential' +``` + +

+ +\subsection user_credential_modify_credential_cmd UserCredential/ModifyCredential Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/ModifyCredential +[PREFIX]/UserCredential/GeneratedCommands/ModifyCredential +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster ModifyCredential Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "CredentialType": { + "type": "CredType" + }, + "CredentialSlot": { + "type": "integer" + }, + "CredentialData": { + "type": "string" + } + }, + "required": [ + "UserUniqueID", + "CredentialType", + "CredentialSlot", + "CredentialData" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/ModifyCredential command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/ModifyCredential' -m '{ "UserUniqueID": ,"CredentialType": ,"CredentialSlot": ,"CredentialData": }' +``` + +To receive a UserCredential/ModifyCredential generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/ModifyCredential' +``` + +

+ +\subsection user_credential_delete_credential_cmd UserCredential/DeleteCredential Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteCredential +[PREFIX]/UserCredential/GeneratedCommands/DeleteCredential +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteCredential Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "CredentialType": { + "type": "CredType" + }, + "CredentialSlot": { + "type": "integer" + } + }, + "required": [ + "UserUniqueID", + "CredentialType", + "CredentialSlot" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteCredential command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteCredential' -m '{ "UserUniqueID": ,"CredentialType": ,"CredentialSlot": }' +``` + +To receive a UserCredential/DeleteCredential generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteCredential' +``` + +

+ +\subsection user_credential_delete_all_users_cmd UserCredential/DeleteAllUsers Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteAllUsers +[PREFIX]/UserCredential/GeneratedCommands/DeleteAllUsers +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteAllUsers Command Properties", + "type": "object", + "properties": { + }, + "required": [ + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteAllUsers command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteAllUsers' -m '{ }' +``` + +To receive a UserCredential/DeleteAllUsers generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteAllUsers' +``` + +

+ +\subsection user_credential_delete_all_credentials_cmd UserCredential/DeleteAllCredentials Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteAllCredentials +[PREFIX]/UserCredential/GeneratedCommands/DeleteAllCredentials +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteAllCredentials Command Properties", + "type": "object", + "properties": { + }, + "required": [ + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteAllCredentials command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteAllCredentials' -m '{ }' +``` + +To receive a UserCredential/DeleteAllCredentials generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteAllCredentials' +``` + +

+ +\subsection user_credential_delete_all_credentials_by_type_cmd UserCredential/DeleteAllCredentialsByType Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteAllCredentialsByType +[PREFIX]/UserCredential/GeneratedCommands/DeleteAllCredentialsByType +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteAllCredentialsByType Command Properties", + "type": "object", + "properties": { + "CredentialType": { + "type": "CredType" + } + }, + "required": [ + "CredentialType" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteAllCredentialsByType command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteAllCredentialsByType' -m '{ "CredentialType": }' +``` + +To receive a UserCredential/DeleteAllCredentialsByType generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteAllCredentialsByType' +``` + +

+ +\subsection user_credential_delete_all_credentials_for_user_cmd UserCredential/DeleteAllCredentialsForUser Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteAllCredentialsForUser +[PREFIX]/UserCredential/GeneratedCommands/DeleteAllCredentialsForUser +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteAllCredentialsForUser Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + } + }, + "required": [ + "UserUniqueID" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteAllCredentialsForUser command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteAllCredentialsForUser' -m '{ "UserUniqueID": }' +``` + +To receive a UserCredential/DeleteAllCredentialsForUser generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteAllCredentialsForUser' +``` + +

+ +\subsection user_credential_delete_all_credentials_for_user_by_type_cmd UserCredential/DeleteAllCredentialsForUserByType Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeleteAllCredentialsForUserByType +[PREFIX]/UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeleteAllCredentialsForUserByType Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "CredentialType": { + "type": "CredType" + } + }, + "required": [ + "UserUniqueID", + "CredentialType" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeleteAllCredentialsForUserByType command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeleteAllCredentialsForUserByType' -m '{ "UserUniqueID": ,"CredentialType": }' +``` + +To receive a UserCredential/DeleteAllCredentialsForUserByType generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType' +``` + +

+ +\subsection user_credential_credential_learn_start_add_cmd UserCredential/CredentialLearnStartAdd Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/CredentialLearnStartAdd +[PREFIX]/UserCredential/GeneratedCommands/CredentialLearnStartAdd +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster CredentialLearnStartAdd Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "CredentialType": { + "type": "CredType" + }, + "CredentialSlot": { + "type": "integer" + }, + "CredentialLearnTimeout": { + "type": "integer" + } + }, + "required": [ + "UserUniqueID", + "CredentialType", + "CredentialSlot", + "CredentialLearnTimeout" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/CredentialLearnStartAdd command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/CredentialLearnStartAdd' -m '{ "UserUniqueID": ,"CredentialType": ,"CredentialSlot": ,"CredentialLearnTimeout": }' +``` + +To receive a UserCredential/CredentialLearnStartAdd generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/CredentialLearnStartAdd' +``` + +

+ +\subsection user_credential_credential_learn_start_modify_cmd UserCredential/CredentialLearnStartModify Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/CredentialLearnStartModify +[PREFIX]/UserCredential/GeneratedCommands/CredentialLearnStartModify +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster CredentialLearnStartModify Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + }, + "CredentialType": { + "type": "CredType" + }, + "CredentialSlot": { + "type": "integer" + }, + "CredentialLearnTimeout": { + "type": "integer" + } + }, + "required": [ + "UserUniqueID", + "CredentialType", + "CredentialSlot", + "CredentialLearnTimeout" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/CredentialLearnStartModify command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/CredentialLearnStartModify' -m '{ "UserUniqueID": ,"CredentialType": ,"CredentialSlot": ,"CredentialLearnTimeout": }' +``` + +To receive a UserCredential/CredentialLearnStartModify generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/CredentialLearnStartModify' +``` + +

+ +\subsection user_credential_credential_learn_stop_cmd UserCredential/CredentialLearnStop Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/CredentialLearnStop +[PREFIX]/UserCredential/GeneratedCommands/CredentialLearnStop +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster CredentialLearnStop Command Properties", + "type": "object", + "properties": { + }, + "required": [ + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/CredentialLearnStop command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/CredentialLearnStop' -m '{ }' +``` + +To receive a UserCredential/CredentialLearnStop generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/CredentialLearnStop' +``` + +

+ +\subsection user_credential_credential_association_cmd UserCredential/CredentialAssociation Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/CredentialAssociation +[PREFIX]/UserCredential/GeneratedCommands/CredentialAssociation +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster CredentialAssociation Command Properties", + "type": "object", + "properties": { + "CredentialType": { + "type": "CredType" + }, + "SourceUserUniqueID": { + "type": "integer" + }, + "SourceCredentialSlot": { + "type": "integer" + }, + "DestinationUserUniqueID": { + "type": "integer" + }, + "DestinationCredentialSlot": { + "type": "integer" + } + }, + "required": [ + "CredentialType", + "SourceUserUniqueID", + "SourceCredentialSlot", + "DestinationUserUniqueID", + "DestinationCredentialSlot" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/CredentialAssociation command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/CredentialAssociation' -m '{ "CredentialType": ,"SourceUserUniqueID": ,"SourceCredentialSlot": ,"DestinationUserUniqueID": ,"DestinationCredentialSlot": }' +``` + +To receive a UserCredential/CredentialAssociation generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/CredentialAssociation' +``` + +

+ +\subsection user_credential_get_user_checksum_cmd UserCredential/GetUserChecksum Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/GetUserChecksum +[PREFIX]/UserCredential/GeneratedCommands/GetUserChecksum +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster GetUserChecksum Command Properties", + "type": "object", + "properties": { + "UserUniqueID": { + "type": "integer" + } + }, + "required": [ + "UserUniqueID" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/GetUserChecksum command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/GetUserChecksum' -m '{ "UserUniqueID": }' +``` + +To receive a UserCredential/GetUserChecksum generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/GetUserChecksum' +``` + +

+ +\subsection user_credential_get_credential_checksum_cmd UserCredential/GetCredentialChecksum Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/GetCredentialChecksum +[PREFIX]/UserCredential/GeneratedCommands/GetCredentialChecksum +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster GetCredentialChecksum Command Properties", + "type": "object", + "properties": { + "CredentialType": { + "type": "CredType" + } + }, + "required": [ + "CredentialType" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/GetCredentialChecksum command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/GetCredentialChecksum' -m '{ "CredentialType": }' +``` + +To receive a UserCredential/GetCredentialChecksum generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/GetCredentialChecksum' +``` + +

+ +\subsection user_credential_get_all_users_checksum_cmd UserCredential/GetAllUsersChecksum Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/GetAllUsersChecksum +[PREFIX]/UserCredential/GeneratedCommands/GetAllUsersChecksum +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster GetAllUsersChecksum Command Properties", + "type": "object", + "properties": { + }, + "required": [ + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/GetAllUsersChecksum command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/GetAllUsersChecksum' -m '{ }' +``` + +To receive a UserCredential/GetAllUsersChecksum generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/GetAllUsersChecksum' +``` + +

+ +\subsection user_credential_set_admin_pin_code_cmd UserCredential/SetAdminPINCode Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/SetAdminPINCode +[PREFIX]/UserCredential/GeneratedCommands/SetAdminPINCode +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster SetAdminPINCode Command Properties", + "type": "object", + "properties": { + "PINCode": { + "type": "string" + } + }, + "required": [ + "PINCode" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/SetAdminPINCode command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/SetAdminPINCode' -m '{ "PINCode": }' +``` + +To receive a UserCredential/SetAdminPINCode generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/SetAdminPINCode' +``` + +

+ +\subsection user_credential_deactivate_admin_pin_code_cmd UserCredential/DeactivateAdminPINCode Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/DeactivateAdminPINCode +[PREFIX]/UserCredential/GeneratedCommands/DeactivateAdminPINCode +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster DeactivateAdminPINCode Command Properties", + "type": "object", + "properties": { + }, + "required": [ + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To send a UserCredential/DeactivateAdminPINCode command under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/DeactivateAdminPINCode' -m '{ }' +``` + +To receive a UserCredential/DeactivateAdminPINCode generated command from a UNID/endpoint: + +```console +mosquitto_sub -t 'ucl/by-unid///UserCredential/GeneratedCommands/DeactivateAdminPINCode' +``` + +

+ +\subsection user_credential_write_attr_cmd UserCredential/WriteAttributes Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/WriteAttributes +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster WriteAttributes Command Properties", + "type": "object", + "properties": { + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To update all UserCredential attributes under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/WriteAttributes' -m '{ }' +``` + +> NOTE: Specify only the list of attributes to write in this command. +> Unspecified attributes will not be updated. + +

+ +\subsection user_credential_force_read_attr_cmd UserCredential/ForceReadAttributes Command + +**MQTT Topic Pattern:** + +``` +[PREFIX]/UserCredential/Commands/ForceReadAttributes +``` + +**MQTT Payload JSON Schema:** + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredential Cluster ForceReadAttributes Command Properties", + "type": "object", + "properties": { + "value": { + "type": "array" + "items": { + "type": "string", + "enum": [ + "SupportedUserUniqueIdentifiers", + "SupportedCredentialRules", + "SupportedCredentialTypes", + "SupportedUserTypes", + "SupportCredentialChecksum", + "SupportAdminPinCode", + "SupportAdminPinCodeDeactivation", + "AdminPinCode" + ] + } + } + }, + "required": [ + "value" + ] +} +``` + +**Example Mosquitto CLI Tool Usage** + +To force read all UserCredential attributes under the by-unid topic space (by sending an empty array): + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/ForceReadAttributes' -m '{ "value": [] }' +``` + +To force read one of the UserCredential attributes under the by-unid topic space: + +```console +mosquitto_pub -t 'ucl/by-unid///UserCredential/Commands/ForceReadAttributes' -m '{ "value": ["SupportedUserUniqueIdentifiers"] }' +``` + + + + + +


+ + @@ -56095,33 +57660,6 @@ mosquitto_pub -t 'ucl/by-unid///UnifyHumidityControl/Commands/ForceRea

- - - -\section struct_credential_struct CredentialStruct Struct - -```json -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "CredentialStruct Struct Properties", - "type": "object", - "properties": { - "CredentialType": { - "type": "CredentialTypeEnum" - } - "CredentialIndex": { - "type": "integer" - } - } -} -``` - - - - - -

- @@ -57305,6 +58843,62 @@ mosquitto_pub -t 'ucl/by-unid///UnifyHumidityControl/Commands/ForceRea

+ + + +\section enum_cred_rule CredRule Enum + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CredRule Enum Properties", + "type": "string", + "enum": [ + "Single", + "Dual", + "Triple" + ] +} +``` + + + + + +

+ + + + +\section enum_cred_type CredType Enum + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CredType Enum Properties", + "type": "string", + "enum": [ + "PINCode", + "Password", + "RFIDCode", + "BLE", + "NFC", + "UWB", + "EyeBiometric", + "FaceBiometric", + "FingerBiometric", + "HandBiometric", + "UnspecifiedBiometric" + ] +} +``` + + + + + +

+ @@ -59710,6 +61304,84 @@ mosquitto_pub -t 'ucl/by-unid///UnifyHumidityControl/Commands/ForceRea

+ + + +\section enum_user_modifier_type UserModifierType Enum + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserModifierType Enum Properties", + "type": "string", + "enum": [ + "DNE", + "Unknown", + "Z-Wave", + "Locally", + "MobileAppOrOtherIoT" + ] +} +``` + + + + + +

+ + + + +\section enum_user_name_encoding_type UserNameEncodingType Enum + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserNameEncodingType Enum Properties", + "type": "string", + "enum": [ + "ASCII", + "OEMExtendedASCII", + "UTF-16" + ] +} +``` + + + + + +

+ + + + +\section enum_user_type_enum UserTypeEnum Enum + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserTypeEnum Enum Properties", + "type": "string", + "enum": [ + "GeneralUser", + "ProgrammingUser", + "NonAccessUser", + "DuressUser", + "DisposableUser", + "ExpiringUser", + "RemoteOnlyUser" + ] +} +``` + + + + + +

+ @@ -62361,6 +64033,132 @@ mosquitto_pub -t 'ucl/by-unid///UnifyHumidityControl/Commands/ForceRea

+ + + +\section enum_user_credential_supported_credential_rules UserCredentialSupportedCredentialRules Bitmap + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredentialSupportedCredentialRules Enum Properties", + "type": "object", + "properties": { + "Single": { + "type": "boolean" + }, + "Dual": { + "type": "boolean" + }, + "Triple": { + "type": "boolean" + } + } +} +``` + + + + + +

+ + + + +\section enum_user_credential_supported_credential_types UserCredentialSupportedCredentialTypes Bitmap + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredentialSupportedCredentialTypes Enum Properties", + "type": "object", + "properties": { + "PINCode": { + "type": "boolean" + }, + "Password": { + "type": "boolean" + }, + "RFIDCode": { + "type": "boolean" + }, + "BLE": { + "type": "boolean" + }, + "NFC": { + "type": "boolean" + }, + "UWB": { + "type": "boolean" + }, + "EyeBiometric": { + "type": "boolean" + }, + "FaceBiometric": { + "type": "boolean" + }, + "FingerBiometric": { + "type": "boolean" + }, + "HandBiometric": { + "type": "boolean" + }, + "UnspecifiedBiometric": { + "type": "boolean" + } + } +} +``` + + + + + +

+ + + + +\section enum_user_credential_supported_user_types UserCredentialSupportedUserTypes Bitmap + +```json +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "UserCredentialSupportedUserTypes Enum Properties", + "type": "object", + "properties": { + "GeneralUser": { + "type": "boolean" + }, + "ProgrammingUser": { + "type": "boolean" + }, + "NonAccessUser": { + "type": "boolean" + }, + "DuressUser": { + "type": "boolean" + }, + "DisposableUser": { + "type": "boolean" + }, + "ExpiringUser": { + "type": "boolean" + }, + "RemoteOnlyUser": { + "type": "boolean" + } + } +} +``` + + + + + +

+ diff --git a/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c b/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c index b4c8531407..7a30dd808f 100644 --- a/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c +++ b/components/uic_dotdot/zap-generated/src/dotdot_attribute_id_definitions.c @@ -1947,6 +1947,31 @@ const char *uic_dotdot_get_attribute_name(dotdot_cluster_id_t cluster_id, return "Unknown"; } // clang-format off + case DOTDOT_USER_CREDENTIAL_CLUSTER_ID: + // clang-format on + switch (attribute_id) { + // clang-format off + case DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS_ATTRIBUTE_ID: + return "SupportedUserUniqueIdentifiers"; + case DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_ATTRIBUTE_ID: + return "SupportedCredentialRules"; + case DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_ATTRIBUTE_ID: + return "SupportedCredentialTypes"; + case DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_TYPES_ATTRIBUTE_ID: + return "SupportedUserTypes"; + case DOTDOT_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM_ATTRIBUTE_ID: + return "SupportCredentialChecksum"; + case DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_ATTRIBUTE_ID: + return "SupportAdminPinCode"; + case DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION_ATTRIBUTE_ID: + return "SupportAdminPinCodeDeactivation"; + case DOTDOT_USER_CREDENTIAL_ADMIN_PIN_CODE_ATTRIBUTE_ID: + return "AdminPinCode"; + // clang-format on + default: + return "Unknown"; + } + // clang-format off case DOTDOT_AOX_LOCATOR_CLUSTER_ID: // clang-format on switch (attribute_id) { @@ -4415,6 +4440,32 @@ dotdot_attribute_id_t return DOTDOT_CONFIGURATION_PARAMETERS_CONFIGURATION_PARAMETERS_ATTRIBUTE_ID; } break; + case DOTDOT_USER_CREDENTIAL_CLUSTER_ID: + if (strcmp ("SupportedUserUniqueIdentifiers", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS_ATTRIBUTE_ID; + } + if (strcmp ("SupportedCredentialRules", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_ATTRIBUTE_ID; + } + if (strcmp ("SupportedCredentialTypes", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_ATTRIBUTE_ID; + } + if (strcmp ("SupportedUserTypes", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_TYPES_ATTRIBUTE_ID; + } + if (strcmp ("SupportCredentialChecksum", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM_ATTRIBUTE_ID; + } + if (strcmp ("SupportAdminPinCode", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_ATTRIBUTE_ID; + } + if (strcmp ("SupportAdminPinCodeDeactivation", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION_ATTRIBUTE_ID; + } + if (strcmp ("AdminPinCode", attribute_name) == 0) { + return DOTDOT_USER_CREDENTIAL_ADMIN_PIN_CODE_ATTRIBUTE_ID; + } + break; case DOTDOT_AOX_LOCATOR_CLUSTER_ID: if (strcmp ("ReportingMode", attribute_name) == 0) { return DOTDOT_AOX_LOCATOR_REPORTING_MODE_ATTRIBUTE_ID; @@ -6506,6 +6557,31 @@ dotdot_attribute_json_type_t return JSON_TYPE_UNKNOWN; } // clang-format off + case DOTDOT_USER_CREDENTIAL_CLUSTER_ID: + // clang-format on + switch (attribute_id) { + // clang-format off + case DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS_ATTRIBUTE_ID: + return JSON_TYPE_NUMBER; + case DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_ATTRIBUTE_ID: + return JSON_TYPE_NUMBER; + case DOTDOT_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_ATTRIBUTE_ID: + return JSON_TYPE_NUMBER; + case DOTDOT_USER_CREDENTIAL_SUPPORTED_USER_TYPES_ATTRIBUTE_ID: + return JSON_TYPE_NUMBER; + case DOTDOT_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM_ATTRIBUTE_ID: + return JSON_TYPE_BOOL; + case DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_ATTRIBUTE_ID: + return JSON_TYPE_BOOL; + case DOTDOT_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION_ATTRIBUTE_ID: + return JSON_TYPE_BOOL; + case DOTDOT_USER_CREDENTIAL_ADMIN_PIN_CODE_ATTRIBUTE_ID: + return JSON_TYPE_STRING; + // clang-format on + default: + return JSON_TYPE_UNKNOWN; + } + // clang-format off case DOTDOT_AOX_LOCATOR_CLUSTER_ID: // clang-format on switch (attribute_id) { @@ -6982,6 +7058,9 @@ bool uic_dotdot_attribute_is_enum(dotdot_cluster_id_t cluster_id, if (64775 == cluster_id) { } + if (64776 == cluster_id) { + } + if (64784 == cluster_id) { if (1 == attribute_id) { return true; diff --git a/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c b/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c index 8699e827dc..a5c8e4d09b 100644 --- a/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c +++ b/components/uic_dotdot/zap-generated/src/dotdot_cluster_id_definitions.c @@ -120,6 +120,8 @@ const char* uic_dotdot_get_cluster_name(dotdot_cluster_id_t cluster_id) { return "NameAndLocation"; case DOTDOT_CONFIGURATION_PARAMETERS_CLUSTER_ID: return "ConfigurationParameters"; + case DOTDOT_USER_CREDENTIAL_CLUSTER_ID: + return "UserCredential"; case DOTDOT_AOX_LOCATOR_CLUSTER_ID: return "AoXLocator"; case DOTDOT_AOX_POSITION_ESTIMATION_CLUSTER_ID: @@ -293,6 +295,9 @@ dotdot_cluster_id_t uic_dotdot_get_cluster_id(const char* cluster_name) { if (strcmp ("ConfigurationParameters", cluster_name) == 0) { return DOTDOT_CONFIGURATION_PARAMETERS_CLUSTER_ID; } + if (strcmp ("UserCredential", cluster_name) == 0) { + return DOTDOT_USER_CREDENTIAL_CLUSTER_ID; + } if (strcmp ("AoXLocator", cluster_name) == 0) { return DOTDOT_AOX_LOCATOR_CLUSTER_ID; } diff --git a/components/uic_dotdot/zap/addon-base-helper.js b/components/uic_dotdot/zap/addon-base-helper.js index 7ce5016fd5..9ddbef3701 100644 --- a/components/uic_dotdot/zap/addon-base-helper.js +++ b/components/uic_dotdot/zap/addon-base-helper.js @@ -100,6 +100,10 @@ zcl_type_map = (function() { CredentialRuleEnum: 'enum8', ZWaveFanModeEnum: 'enum8', ZWaveFanStateEnum: 'enum8', + CredRule: 'enum8', + UserTypeEnum: 'enum8', + CredType: 'enum8', + UserNameEncodingType: 'enum8', // zclType: 'uint8', BarrierControlSafetyStatus: 'map16', diff --git a/components/uic_dotdot/zap/addon-helper.js b/components/uic_dotdot/zap/addon-helper.js index b670e96dbc..6030046cac 100644 --- a/components/uic_dotdot/zap/addon-helper.js +++ b/components/uic_dotdot/zap/addon-helper.js @@ -124,7 +124,6 @@ function isStruct(type) { case 'NetworkManagementState': return true case 'SSceneTable': return true case 'DeviceTypeStruct': return true - case 'CredentialStruct': return true default: return false } } diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h index e6266c2275..cbabaf4d6b 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt.h @@ -39032,6 +39032,1540 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( void uic_mqtt_dotdot_configuration_parameters_publish_empty_supported_commands( const dotdot_unid_t unid ,dotdot_endpoint_id_t endpoint); +// Callback types used by the user_credential cluster +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_add_user_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + UserTypeEnum user_type, + + bool user_active_state, + + CredRule credential_rule, + + const char* user_name, + + uint16_t expiring_timeout_minutes, + + UserNameEncodingType user_name_encoding + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_modify_user_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + UserTypeEnum user_type, + + bool user_active_state, + + CredRule credential_rule, + + const char* user_name, + + uint16_t expiring_timeout_minutes, + + UserNameEncodingType user_name_encoding + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_user_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_add_credential_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + const char* credential_data + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_modify_credential_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + const char* credential_data + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_credential_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_all_users_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + CredType credential_type + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + CredType credential_type + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + uint8_t credential_learn_timeout + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + uint8_t credential_learn_timeout + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_credential_association_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + CredType credential_type, + + uint16_t source_user_uniqueid, + + uint16_t source_credential_slot, + + uint16_t destination_user_uniqueid, + + uint16_t destination_credential_slot + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uint16_t user_uniqueid + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + CredType credential_type + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + const char* pin_code + +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type +); + +typedef struct { + uint16_t supported_user_unique_identifiers; + uint8_t supported_credential_rules; + uint16_t supported_credential_types; + uint16_t supported_user_types; + bool support_credential_checksum; + bool support_admin_pin_code; + bool support_admin_pin_code_deactivation; + const char* admin_pin_code; +} uic_mqtt_dotdot_user_credential_state_t; + +typedef struct { + bool supported_user_unique_identifiers; + bool supported_credential_rules; + bool supported_credential_types; + bool supported_user_types; + bool support_credential_checksum; + bool support_admin_pin_code; + bool support_admin_pin_code_deactivation; + bool admin_pin_code; +} uic_mqtt_dotdot_user_credential_updated_state_t; + +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_write_attributes_callback_t)( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_user_credential_state_t, + uic_mqtt_dotdot_user_credential_updated_state_t +); + +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t)( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_user_credential_updated_state_t +); + + +/** + * @brief Command fields for UserCredential/AddUser + */ +typedef struct { + uint16_t user_uniqueid; + + UserTypeEnum user_type; + + bool user_active_state; + + CredRule credential_rule; + + const char* user_name; + + uint16_t expiring_timeout_minutes; + + UserNameEncodingType user_name_encoding; +} uic_mqtt_dotdot_user_credential_command_add_user_fields_t; + +/** + * @brief Command fields for UserCredential/ModifyUser + */ +typedef struct { + uint16_t user_uniqueid; + + UserTypeEnum user_type; + + bool user_active_state; + + CredRule credential_rule; + + const char* user_name; + + uint16_t expiring_timeout_minutes; + + UserNameEncodingType user_name_encoding; +} uic_mqtt_dotdot_user_credential_command_modify_user_fields_t; + +/** + * @brief Command fields for UserCredential/DeleteUser + */ +typedef struct { + uint16_t user_uniqueid; +} uic_mqtt_dotdot_user_credential_command_delete_user_fields_t; + +/** + * @brief Command fields for UserCredential/AddCredential + */ +typedef struct { + uint16_t user_uniqueid; + + CredType credential_type; + + uint16_t credential_slot; + + const char* credential_data; +} uic_mqtt_dotdot_user_credential_command_add_credential_fields_t; + +/** + * @brief Command fields for UserCredential/ModifyCredential + */ +typedef struct { + uint16_t user_uniqueid; + + CredType credential_type; + + uint16_t credential_slot; + + const char* credential_data; +} uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t; + +/** + * @brief Command fields for UserCredential/DeleteCredential + */ +typedef struct { + uint16_t user_uniqueid; + + CredType credential_type; + + uint16_t credential_slot; +} uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t; + +/** + * @brief Command fields for UserCredential/DeleteAllCredentialsByType + */ +typedef struct { + CredType credential_type; +} uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t; + +/** + * @brief Command fields for UserCredential/DeleteAllCredentialsForUser + */ +typedef struct { + uint16_t user_uniqueid; +} uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t; + +/** + * @brief Command fields for UserCredential/DeleteAllCredentialsForUserByType + */ +typedef struct { + uint16_t user_uniqueid; + + CredType credential_type; +} uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t; + +/** + * @brief Command fields for UserCredential/CredentialLearnStartAdd + */ +typedef struct { + uint16_t user_uniqueid; + + CredType credential_type; + + uint16_t credential_slot; + + uint8_t credential_learn_timeout; +} uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t; + +/** + * @brief Command fields for UserCredential/CredentialLearnStartModify + */ +typedef struct { + uint16_t user_uniqueid; + + CredType credential_type; + + uint16_t credential_slot; + + uint8_t credential_learn_timeout; +} uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t; + +/** + * @brief Command fields for UserCredential/CredentialAssociation + */ +typedef struct { + CredType credential_type; + + uint16_t source_user_uniqueid; + + uint16_t source_credential_slot; + + uint16_t destination_user_uniqueid; + + uint16_t destination_credential_slot; +} uic_mqtt_dotdot_user_credential_command_credential_association_fields_t; + +/** + * @brief Command fields for UserCredential/GetUserChecksum + */ +typedef struct { + uint16_t user_uniqueid; +} uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t; + +/** + * @brief Command fields for UserCredential/GetCredentialChecksum + */ +typedef struct { + CredType credential_type; +} uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t; + +/** + * @brief Command fields for UserCredential/SetAdminPINCode + */ +typedef struct { + const char* pin_code; +} uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t; + + +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/add_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_add_user_callback_set(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/add_user is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_add_user_callback_unset(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/add_user is received. + */ +void uic_mqtt_dotdot_user_credential_add_user_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/add_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_add_user_callback_set(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/add_user is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_add_user_callback_unset(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/add_user is received. + */ +void uic_mqtt_dotdot_user_credential_generated_add_user_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/modify_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_modify_user_callback_set(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/modify_user is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_modify_user_callback_unset(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/modify_user is received. + */ +void uic_mqtt_dotdot_user_credential_modify_user_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/modify_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_modify_user_callback_set(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/modify_user is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_modify_user_callback_unset(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/modify_user is received. + */ +void uic_mqtt_dotdot_user_credential_generated_modify_user_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_user is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_user is received. + */ +void uic_mqtt_dotdot_user_credential_delete_user_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_user is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_user is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_user_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/add_credential is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_add_credential_callback_set(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/add_credential is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_add_credential_callback_unset(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/add_credential is received. + */ +void uic_mqtt_dotdot_user_credential_add_credential_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/add_credential is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_add_credential_callback_set(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/add_credential is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_add_credential_callback_unset(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/add_credential is received. + */ +void uic_mqtt_dotdot_user_credential_generated_add_credential_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/modify_credential is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_modify_credential_callback_set(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/modify_credential is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_modify_credential_callback_unset(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/modify_credential is received. + */ +void uic_mqtt_dotdot_user_credential_modify_credential_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/modify_credential is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_modify_credential_callback_set(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/modify_credential is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_modify_credential_callback_unset(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/modify_credential is received. + */ +void uic_mqtt_dotdot_user_credential_generated_modify_credential_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_credential is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_credential_callback_set(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_credential is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_credential_callback_unset(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_credential is received. + */ +void uic_mqtt_dotdot_user_credential_delete_credential_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_credential is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_credential_callback_set(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_credential is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_credential_callback_unset(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_credential is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_credential_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_all_users is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_all_users is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_all_users is received. + */ +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_users is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_users is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_all_users is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_all_credentials is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_all_credentials is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_all_credentials is received. + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_all_credentials is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_all_credentials_by_type is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_all_credentials_by_type is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_all_credentials_by_type is received. + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials_by_type is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials_by_type is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_all_credentials_by_type is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_all_credentials_for_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_all_credentials_for_user is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_all_credentials_for_user is received. + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials_for_user is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials_for_user is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_all_credentials_for_user is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/delete_all_credentials_for_user_by_type is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/delete_all_credentials_for_user_by_type is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/delete_all_credentials_for_user_by_type is received. + */ +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials_for_user_by_type is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/delete_all_credentials_for_user_by_type is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/delete_all_credentials_for_user_by_type is received. + */ +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/credential_learn_start_add is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/credential_learn_start_add is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/credential_learn_start_add is received. + */ +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/credential_learn_start_add is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/credential_learn_start_add is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/credential_learn_start_add is received. + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/credential_learn_start_modify is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/credential_learn_start_modify is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/credential_learn_start_modify is received. + */ +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/credential_learn_start_modify is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/credential_learn_start_modify is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/credential_learn_start_modify is received. + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/credential_learn_stop is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/credential_learn_stop is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/credential_learn_stop is received. + */ +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/credential_learn_stop is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/credential_learn_stop is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/credential_learn_stop is received. + */ +void uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/credential_association is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_association_callback_set(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/credential_association is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_credential_association_callback_unset(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/credential_association is received. + */ +void uic_mqtt_dotdot_user_credential_credential_association_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/credential_association is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_association_callback_set(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/credential_association is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_credential_association_callback_unset(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/credential_association is received. + */ +void uic_mqtt_dotdot_user_credential_generated_credential_association_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/get_user_checksum is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/get_user_checksum is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/get_user_checksum is received. + */ +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/get_user_checksum is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/get_user_checksum is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/get_user_checksum is received. + */ +void uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/get_credential_checksum is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/get_credential_checksum is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/get_credential_checksum is received. + */ +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/get_credential_checksum is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/get_credential_checksum is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/get_credential_checksum is received. + */ +void uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/get_all_users_checksum is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/get_all_users_checksum is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/get_all_users_checksum is received. + */ +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/get_all_users_checksum is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/get_all_users_checksum is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/get_all_users_checksum is received. + */ +void uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/set_admin_pin_code is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/set_admin_pin_code is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/set_admin_pin_code is received. + */ +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/set_admin_pin_code is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/set_admin_pin_code is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/set_admin_pin_code is received. + */ +void uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback_clear(); +/** + * @brief Setup callback to be called when a + * UserCredential/Commands/deactivate_admin_pin_code is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback); +/** + * @brief Unsets callback to be called when a + * UserCredential/Commands/deactivate_admin_pin_code is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * UserCredential/Commands/deactivate_admin_pin_code is received. + */ +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_clear(); + +/** + * @brief Setup callback to be called when a + * +/UserCredential/GeneratedCommands/deactivate_admin_pin_code is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback); +/** + * @brief Unsets callback to be called when a + * +/UserCredential/GeneratedCommands/deactivate_admin_pin_code is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback); +/** + * @brief Clears all callbacks registered for when + * +/UserCredential/GeneratedCommands/deactivate_admin_pin_code is received. + */ +void uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback_clear(); + +/** + * @brief Setup a callback for WriteAttribute to be called when a + * +/user_credential/Commands/WriteAttributes is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_set_user_credential_write_attributes_callback( + const uic_mqtt_dotdot_user_credential_write_attributes_callback_t callback +); +/** + * @brief Unsets a callback for WriteAttribute to be called when a + * +/user_credential/Commands/WriteAttributes is received. + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_unset_user_credential_write_attributes_callback( + const uic_mqtt_dotdot_user_credential_write_attributes_callback_t callback +); +/** + * @brief Clears all callbacks registered for when + * +/user_credential/Commands/WriteAttributes is received. + */ +void uic_mqtt_dotdot_clear_user_credential_write_attributes_callbacks(); + +/** + * @brief Setup a callback for ForceReadAttributes to be called when a + * +/user_credential/Commands/ForceReadAttributes is received. + * + * Setting this callback will not overwrite the previous set callback + * @param callback Function to be called on command reception + */ +void uic_mqtt_dotdot_set_user_credential_force_read_attributes_callback( + const uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t callback +); +/** + * @brief Unsets a callback for ForceReadAttributes to be called when a + * +/user_credential/Commands/ForceReadAttributes is received. + * + * @param callback Function to be no longer called on command reception + */ +void uic_mqtt_dotdot_unset_user_credential_force_read_attributes_callback( + const uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t callback +); +/** + * @brief Clears all callbacks registered for when + * +/user_credential/Commands/ForceReadAttributes is received. + */ +void uic_mqtt_dotdot_clear_user_credential_force_read_attributes_callbacks(); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportedUserUniqueIdentifiers + * + * @param base_topic topic prefix to publish, /supported_user_unique_identifiers + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportedUserUniqueIdentifiers + * + * @param base_topic topic prefix to publish, /supported_user_unique_identifiers + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportedCredentialRules + * + * @param base_topic topic prefix to publish, /supported_credential_rules + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_rules_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportedCredentialRules + * + * @param base_topic topic prefix to publish, /supported_credential_rules + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_rules_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportedCredentialTypes + * + * @param base_topic topic prefix to publish, /supported_credential_types + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_types_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportedCredentialTypes + * + * @param base_topic topic prefix to publish, /supported_credential_types + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_types_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportedUserTypes + * + * @param base_topic topic prefix to publish, /supported_user_types + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_types_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportedUserTypes + * + * @param base_topic topic prefix to publish, /supported_user_types + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_types_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportCredentialChecksum + * + * @param base_topic topic prefix to publish, /support_credential_checksum + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_support_credential_checksum_publish( + const char *base_topic, + bool value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportCredentialChecksum + * + * @param base_topic topic prefix to publish, /support_credential_checksum + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_support_credential_checksum_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportAdminPinCode + * + * @param base_topic topic prefix to publish, /support_admin_pin_code + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_publish( + const char *base_topic, + bool value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportAdminPinCode + * + * @param base_topic topic prefix to publish, /support_admin_pin_code + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/SupportAdminPinCodeDeactivation + * + * @param base_topic topic prefix to publish, /support_admin_pin_code_deactivation + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_publish( + const char *base_topic, + bool value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/SupportAdminPinCodeDeactivation + * + * @param base_topic topic prefix to publish, /support_admin_pin_code_deactivation + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Publish the attribute; UserCredential/Attributes/AdminPinCode + * + * @param base_topic topic prefix to publish, /admin_pin_code + * will be appended + * @param value Value to publish + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_admin_pin_code_publish( + const char *base_topic, + const char* value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + +/** + * @brief Unretains a published attribute; UserCredential/Attributes/AdminPinCode + * + * @param base_topic topic prefix to publish, /admin_pin_code + * will be appended + * @param publish_type Whether to publish as Desired, Reported, or Both. + * + * @returns SL_STATUS_OK on success + */ +sl_status_t uic_mqtt_dotdot_user_credential_admin_pin_code_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +); + + +/** + * @brief Publish the UserCredential/ClusterRevision attribute + * + * @param base_topic topic prefix to publish, /UserCredential/Attributes/ClusterRevision + * will be appended. + * @param value Value to publish. + */ +void uic_mqtt_dotdot_user_credential_publish_cluster_revision(const char* base_topic, uint16_t value); + +/** + * @brief Unretain a publication to UserCredential/ClusterRevision attribute + * + * @param base_topic topic prefix to publish, /UserCredential/Attributes/ClusterRevision + * will be appended. + */ +void uic_mqtt_dotdot_user_credential_unretain_cluster_revision(const char* base_topic); + +/** + * @brief Publish the SupportedCommands for UNID/EndPoint for the UserCredential Cluster + * + * This function will iterate over all Commands in the UserCredential Cluster and + * call all registered callback functions with UNID/endpoint, and + * callback_type = UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK. + * All Cluster Command callback functions that return SL_STATUS_OK + * will be added to the list of supported commands and published. + * + * @param unid + * @param endpoint + */ +void uic_mqtt_dotdot_user_credential_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint); + +/** + * @brief Publish an empty array of SupportedCommands for UNID/EndPoint for + * the UserCredential Cluster + * + * @param unid + * @param endpoint ) + */ +void uic_mqtt_dotdot_user_credential_publish_empty_supported_commands( + const dotdot_unid_t unid + ,dotdot_endpoint_id_t endpoint); // Callback types used by the aox_locator cluster typedef sl_status_t (*uic_mqtt_dotdot_aox_locator_iq_report_callback_t)( dotdot_unid_t unid, diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h index 5ec718c5ef..5dbe91f4d7 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_attributes.h @@ -4978,6 +4978,63 @@ typedef sl_status_t (*uic_mqtt_dotdot_configuration_parameters_attribute_configu size_t configuration_parameters_count, const ConfigurationParameter* configuration_parameters ); +// Callback types used by the user_credential cluster +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + uint16_t supported_user_unique_identifiers +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + uint8_t supported_credential_rules +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + uint16_t supported_credential_types +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + uint16_t supported_user_types +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + bool support_credential_checksum +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + bool support_admin_pin_code +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + bool support_admin_pin_code_deactivation +); +typedef sl_status_t (*uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback_t)( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + bool unretained, + uic_mqtt_dotdot_attribute_update_type_t update_type, + const char* admin_pin_code +); // Callback types used by the aox_locator cluster typedef sl_status_t (*uic_mqtt_dotdot_aox_locator_attribute_reporting_mode_callback_t)( dotdot_unid_t unid, @@ -9878,6 +9935,62 @@ sl_status_t uic_mqtt_dotdot_configuration_parameters_attributes_init(); void uic_mqtt_dotdot_configuration_parameters_attribute_configuration_parameters_callback_set(const uic_mqtt_dotdot_configuration_parameters_attribute_configuration_parameters_callback_t callback); +/** + * Initializes the attributes features for the UserCredential cluster, + * allowing to receive attribute updates from other UNIDs. + */ +sl_status_t uic_mqtt_dotdot_user_credential_attributes_init(); + +/** + * Setup callback to be called when a + * UserCredential/Attributes/supported_user_unique_identifiers/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/supported_credential_rules/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/supported_credential_types/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/supported_user_types/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/support_credential_checksum/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback_set(const uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/support_admin_pin_code/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/support_admin_pin_code_deactivation/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback_set(const uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback_t callback); +/** + * Setup callback to be called when a + * UserCredential/Attributes/admin_pin_code/# is received. Setting + * this callback will overwrite the previous set callback + */ +void uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback_t callback); + + /** * Initializes the attributes features for the AoXLocator cluster, * allowing to receive attribute updates from other UNIDs. diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h index acb9e001f6..4b8c503291 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_generated_commands.h @@ -4824,6 +4824,428 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_write_attributes uic_mqtt_dotdot_configuration_parameters_updated_state_t attribute_list ); +/** + * @brief Publishes an incoming/generated AddUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/AddUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_add_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated ModifyUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/ModifyUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_modify_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated DeleteUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated AddCredential command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/AddCredential + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_add_credential_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated ModifyCredential command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/ModifyCredential + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_modify_credential_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated DeleteCredential command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteCredential + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_credential_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated DeleteAllUsers command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllUsers + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_users_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +); +/** + * @brief Publishes an incoming/generated DeleteAllCredentials command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentials + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +); +/** + * @brief Publishes an incoming/generated DeleteAllCredentialsByType command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsByType + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_by_type_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated DeleteAllCredentialsForUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsForUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_for_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated DeleteAllCredentialsForUserByType command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_for_user_by_type_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated CredentialLearnStartAdd command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStartAdd + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_start_add_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated CredentialLearnStartModify command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStartModify + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_start_modify_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated CredentialLearnStop command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStop + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_stop_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +); +/** + * @brief Publishes an incoming/generated CredentialAssociation command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialAssociation + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_association_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated GetUserChecksum command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetUserChecksum + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_get_user_checksum_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated GetCredentialChecksum command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetCredentialChecksum + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_get_credential_checksum_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated GetAllUsersChecksum command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetAllUsersChecksum + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_get_all_users_checksum_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +); +/** + * @brief Publishes an incoming/generated SetAdminPINCode command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/SetAdminPINCode + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_set_admin_pin_code_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +); +/** + * @brief Publishes an incoming/generated DeactivateAdminPINCode command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeactivateAdminPINCode + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_deactivate_admin_pin_code_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +); + +/** + * @brief Publishes an incoming/generated WriteAttributes command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/WriteAttributes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * @param attribute_values Values to assign to the attributes + * @param attribute_list List of attributes that are written + */ +void uic_mqtt_dotdot_user_credential_publish_generated_write_attributes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_user_credential_state_t attribute_values, + uic_mqtt_dotdot_user_credential_updated_state_t attribute_list +); + /** * @brief Publishes an incoming/generated IQReport command for * the AoXLocator cluster. diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h index eca854c94e..18a9f97b6b 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_group_commands.h @@ -3610,6 +3610,338 @@ void uic_mqtt_dotdot_by_group_configuration_parameters_write_attributes_callback +/** + * @brief Callback signature for by-group UserCredential::AddUser command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_add_user_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/add_user is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_add_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_add_user_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::ModifyUser command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_modify_user_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/modify_user is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_modify_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_modify_user_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteUser command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_user_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_user is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_user_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::AddCredential command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_add_credential_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/add_credential is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_add_credential_callback_set(const uic_mqtt_dotdot_by_group_user_credential_add_credential_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::ModifyCredential command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/modify_credential is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback_set(const uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteCredential command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_credential is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteAllUsers command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback_t)( + const dotdot_group_id_t group_id +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_all_users is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteAllCredentials command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback_t)( + const dotdot_group_id_t group_id +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_all_credentials is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteAllCredentialsByType command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_all_credentials_by_type is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteAllCredentialsForUser command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_all_credentials_for_user is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeleteAllCredentialsForUserByType command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/delete_all_credentials_for_user_by_type is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::CredentialLearnStartAdd command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/credential_learn_start_add is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::CredentialLearnStartModify command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/credential_learn_start_modify is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::CredentialLearnStop command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback_t)( + const dotdot_group_id_t group_id +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/credential_learn_stop is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::CredentialAssociation command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_credential_association_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/credential_association is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_credential_association_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_association_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::GetUserChecksum command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/get_user_checksum is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback_set(const uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::GetCredentialChecksum command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/get_credential_checksum is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback_set(const uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::GetAllUsersChecksum command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback_t)( + const dotdot_group_id_t group_id +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/get_all_users_checksum is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback_set(const uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::SetAdminPINCode command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback_t)( + const dotdot_group_id_t group_id, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/set_admin_pin_code is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback_set(const uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback_t callback); + +/** + * @brief Callback signature for by-group UserCredential::DeactivateAdminPINCode command. + */ +typedef void (*uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback_t)( + const dotdot_group_id_t group_id +); + +/** + * Setup handler to be called when a + * ucl/by-group/+/UserCredential/deactivate_admin_pin_code is received. + * Setting this callback will overwrite the previous set callback. + * + */ +void uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback_set(const uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback_t callback); + +typedef void (*uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback_t)( + const dotdot_group_id_t group_id, + uic_mqtt_dotdot_user_credential_state_t, + uic_mqtt_dotdot_user_credential_updated_state_t +); + +/** + * Setup a callback for WriteAttribute to be called when a + * ucl/by-group/+/user_credential/Commands/WriteAttributes is received. + * Setting this callback will overwrite any previously set callback. + */ +void uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback_set( + const uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback_t callback +); + + + /** * @brief Callback signature for by-group AoXLocator::IQReport command. */ diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h index 80d87abc45..bec991c7cf 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.h @@ -216,6 +216,20 @@ char *commissioning_startup_control_get_enum_value_name_c( uint32_t value, char *result, size_t max_result_size); /** Get commissioning_startup_control enum representation from string. */ uint32_t commissioning_startup_control_get_enum_value_number_c(const char *str); +#define CRED_RULE_ENUM_NAME_AVAILABLE 1 + +/** Get cred_rule string representation from enum. */ +char *cred_rule_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size); +/** Get cred_rule enum representation from string. */ +uint32_t cred_rule_get_enum_value_number_c(const char *str); +#define CRED_TYPE_ENUM_NAME_AVAILABLE 1 + +/** Get cred_type string representation from enum. */ +char *cred_type_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size); +/** Get cred_type enum representation from string. */ +uint32_t cred_type_get_enum_value_number_c(const char *str); #define CREDENTIAL_RULE_ENUM_ENUM_NAME_AVAILABLE 1 /** Get credential_rule_enum string representation from enum. */ @@ -860,6 +874,27 @@ char *unify_thermostat_thermostat_mode_get_enum_value_name_c( uint32_t value, char *result, size_t max_result_size); /** Get unify_thermostat_thermostat_mode enum representation from string. */ uint32_t unify_thermostat_thermostat_mode_get_enum_value_number_c(const char *str); +#define USER_MODIFIER_TYPE_ENUM_NAME_AVAILABLE 1 + +/** Get user_modifier_type string representation from enum. */ +char *user_modifier_type_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size); +/** Get user_modifier_type enum representation from string. */ +uint32_t user_modifier_type_get_enum_value_number_c(const char *str); +#define USER_NAME_ENCODING_TYPE_ENUM_NAME_AVAILABLE 1 + +/** Get user_name_encoding_type string representation from enum. */ +char *user_name_encoding_type_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size); +/** Get user_name_encoding_type enum representation from string. */ +uint32_t user_name_encoding_type_get_enum_value_number_c(const char *str); +#define USER_TYPE_ENUM_ENUM_NAME_AVAILABLE 1 + +/** Get user_type_enum string representation from enum. */ +char *user_type_enum_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size); +/** Get user_type_enum enum representation from string. */ +uint32_t user_type_enum_get_enum_value_number_c(const char *str); #define WINDOW_COVERING_WINDOW_COVERING_TYPE_ENUM_NAME_AVAILABLE 1 /** Get window_covering_window_covering_type string representation from enum. */ diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp index 14befa43ce..14e4a8f211 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_helpers.hpp @@ -489,6 +489,40 @@ std::string commissioning_startup_control_get_enum_value_name( */ uint32_t commissioning_startup_control_get_enum_value_number(const std::string &str); +#define CRED_RULE_ENUM_NAME_AVAILABLE 1 + +/** + * @brief Finds the name of a field for the CredRule enum + * + * @returns A string representation of the value. + */ +std::string cred_rule_get_enum_value_name( + uint32_t value); + +/** + * @brief Finds the enum number of a string representation for the CredRule enum + * + * @returns A number enum value. + */ +uint32_t cred_rule_get_enum_value_number(const std::string &str); + +#define CRED_TYPE_ENUM_NAME_AVAILABLE 1 + +/** + * @brief Finds the name of a field for the CredType enum + * + * @returns A string representation of the value. + */ +std::string cred_type_get_enum_value_name( + uint32_t value); + +/** + * @brief Finds the enum number of a string representation for the CredType enum + * + * @returns A number enum value. + */ +uint32_t cred_type_get_enum_value_number(const std::string &str); + #define CREDENTIAL_RULE_ENUM_ENUM_NAME_AVAILABLE 1 /** @@ -2053,6 +2087,57 @@ std::string unify_thermostat_thermostat_mode_get_enum_value_name( */ uint32_t unify_thermostat_thermostat_mode_get_enum_value_number(const std::string &str); +#define USER_MODIFIER_TYPE_ENUM_NAME_AVAILABLE 1 + +/** + * @brief Finds the name of a field for the UserModifierType enum + * + * @returns A string representation of the value. + */ +std::string user_modifier_type_get_enum_value_name( + uint32_t value); + +/** + * @brief Finds the enum number of a string representation for the UserModifierType enum + * + * @returns A number enum value. + */ +uint32_t user_modifier_type_get_enum_value_number(const std::string &str); + +#define USER_NAME_ENCODING_TYPE_ENUM_NAME_AVAILABLE 1 + +/** + * @brief Finds the name of a field for the UserNameEncodingType enum + * + * @returns A string representation of the value. + */ +std::string user_name_encoding_type_get_enum_value_name( + uint32_t value); + +/** + * @brief Finds the enum number of a string representation for the UserNameEncodingType enum + * + * @returns A number enum value. + */ +uint32_t user_name_encoding_type_get_enum_value_number(const std::string &str); + +#define USER_TYPE_ENUM_ENUM_NAME_AVAILABLE 1 + +/** + * @brief Finds the name of a field for the UserTypeEnum enum + * + * @returns A string representation of the value. + */ +std::string user_type_enum_get_enum_value_name( + uint32_t value); + +/** + * @brief Finds the enum number of a string representation for the UserTypeEnum enum + * + * @returns A number enum value. + */ +uint32_t user_type_enum_get_enum_value_number(const std::string &str); + #define WINDOW_COVERING_WINDOW_COVERING_TYPE_ENUM_NAME_AVAILABLE 1 /** diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h index 3d57ce907f..a75984021a 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_send_commands.h @@ -6982,6 +6982,746 @@ void uic_mqtt_dotdot_configuration_parameters_publish_discover_parameter_range_c const uic_mqtt_dotdot_configuration_parameters_command_discover_parameter_range_fields_t *fields ); +/** + * @brief Sends/Publishes a AddUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/AddUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +); + +/** + * @brief Sends/Publishes a AddUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/AddUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +); +/** + * @brief Sends/Publishes a ModifyUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/ModifyUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +); + +/** + * @brief Sends/Publishes a ModifyUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/ModifyUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +); +/** + * @brief Sends/Publishes a DeleteUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +); + +/** + * @brief Sends/Publishes a DeleteUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +); +/** + * @brief Sends/Publishes a AddCredential command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/AddCredential + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_credential_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +); + +/** + * @brief Sends/Publishes a AddCredential command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/AddCredential + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_credential_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +); +/** + * @brief Sends/Publishes a ModifyCredential command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/ModifyCredential + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_credential_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +); + +/** + * @brief Sends/Publishes a ModifyCredential command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/ModifyCredential + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_credential_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +); +/** + * @brief Sends/Publishes a DeleteCredential command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteCredential + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_credential_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +); + +/** + * @brief Sends/Publishes a DeleteCredential command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteCredential + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_credential_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +); +/** + * @brief Sends/Publishes a DeleteAllUsers command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllUsers + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_users_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +); + +/** + * @brief Sends/Publishes a DeleteAllUsers command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllUsers + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_users_command_to_group( + uint16_t destination_group_id +); +/** + * @brief Sends/Publishes a DeleteAllCredentials command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentials + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +); + +/** + * @brief Sends/Publishes a DeleteAllCredentials command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentials + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_command_to_group( + uint16_t destination_group_id +); +/** + * @brief Sends/Publishes a DeleteAllCredentialsByType command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentialsByType + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_by_type_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +); + +/** + * @brief Sends/Publishes a DeleteAllCredentialsByType command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentialsByType + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_by_type_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +); +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentialsForUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +); + +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentialsForUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +); +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUserByType command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentialsForUserByType + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_by_type_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +); + +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUserByType command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentialsForUserByType + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_by_type_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +); +/** + * @brief Sends/Publishes a CredentialLearnStartAdd command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialLearnStartAdd + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_add_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +); + +/** + * @brief Sends/Publishes a CredentialLearnStartAdd command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialLearnStartAdd + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_add_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +); +/** + * @brief Sends/Publishes a CredentialLearnStartModify command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialLearnStartModify + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_modify_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +); + +/** + * @brief Sends/Publishes a CredentialLearnStartModify command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialLearnStartModify + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_modify_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +); +/** + * @brief Sends/Publishes a CredentialLearnStop command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialLearnStop + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_stop_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +); + +/** + * @brief Sends/Publishes a CredentialLearnStop command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialLearnStop + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_stop_command_to_group( + uint16_t destination_group_id +); +/** + * @brief Sends/Publishes a CredentialAssociation command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialAssociation + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_association_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +); + +/** + * @brief Sends/Publishes a CredentialAssociation command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialAssociation + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_association_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +); +/** + * @brief Sends/Publishes a GetUserChecksum command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/GetUserChecksum + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_user_checksum_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +); + +/** + * @brief Sends/Publishes a GetUserChecksum command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/GetUserChecksum + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_user_checksum_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +); +/** + * @brief Sends/Publishes a GetCredentialChecksum command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/GetCredentialChecksum + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_credential_checksum_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +); + +/** + * @brief Sends/Publishes a GetCredentialChecksum command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/GetCredentialChecksum + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_credential_checksum_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +); +/** + * @brief Sends/Publishes a GetAllUsersChecksum command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/GetAllUsersChecksum + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_all_users_checksum_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +); + +/** + * @brief Sends/Publishes a GetAllUsersChecksum command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/GetAllUsersChecksum + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_all_users_checksum_command_to_group( + uint16_t destination_group_id +); +/** + * @brief Sends/Publishes a SetAdminPINCode command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/SetAdminPINCode + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_set_admin_pin_code_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +); + +/** + * @brief Sends/Publishes a SetAdminPINCode command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/SetAdminPINCode + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_set_admin_pin_code_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +); +/** + * @brief Sends/Publishes a DeactivateAdminPINCode command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeactivateAdminPINCode + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_deactivate_admin_pin_code_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +); + +/** + * @brief Sends/Publishes a DeactivateAdminPINCode command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeactivateAdminPINCode + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_deactivate_admin_pin_code_command_to_group( + uint16_t destination_group_id +); /** * @brief Sends/Publishes a IQReport command for * the AoXLocator cluster to a destination. diff --git a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h index 0f76ceda79..e26174d308 100644 --- a/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h +++ b/components/uic_dotdot_mqtt/zap-generated/include/dotdot_mqtt_supported_generated_commands.h @@ -1551,6 +1551,54 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_generated_comman ); +/** + * @brief Struct containing the list of commands for UserCredential + */ +typedef struct _uic_mqtt_dotdot_user_credential_supported_commands_ { + bool add_user; + bool modify_user; + bool delete_user; + bool add_credential; + bool modify_credential; + bool delete_credential; + bool delete_all_users; + bool delete_all_credentials; + bool delete_all_credentials_by_type; + bool delete_all_credentials_for_user; + bool delete_all_credentials_for_user_by_type; + bool credential_learn_start_add; + bool credential_learn_start_modify; + bool credential_learn_stop; + bool credential_association; + bool get_user_checksum; + bool get_credential_checksum; + bool get_all_users_checksum; + bool set_admin_pin_code; + bool deactivate_admin_pin_code; + bool write_attributes; +} uic_mqtt_dotdot_user_credential_supported_commands_t; + +/** + * @brief Sends/Publishes a the SupportedGenerated commands for + * the UserCredential cluster for a UNID/Endpoint + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/SupportedGeneratedCommands + * + * @param unid The UNID of the node on behalf of which the advertisment is made + * + * @param endpoint The Endpoint ID of the node on behalf of which the advertisment is made + * + * @param command_list Struct pointer with the fields value indicating if + * individual commands can be generated. + */ +void uic_mqtt_dotdot_user_credential_publish_supported_generated_commands( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_supported_commands_t *command_list +); + + /** * @brief Struct containing the list of commands for AoXLocator */ diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp index 90032e728b..30417beee6 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.cpp @@ -91684,323 +91684,757 @@ sl_status_t uic_mqtt_dotdot_configuration_parameters_init() } // Callbacks pointers -static std::set uic_mqtt_dotdot_aox_locator_iq_report_callback; -static std::set uic_mqtt_dotdot_aox_locator_generated_iq_report_callback; -static std::set uic_mqtt_dotdot_aox_locator_angle_report_callback; -static std::set uic_mqtt_dotdot_aox_locator_generated_angle_report_callback; -static std::set uic_mqtt_dotdot_aox_locator_angle_correction_callback; -static std::set uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback; -static std::set uic_mqtt_dotdot_aox_locator_write_attributes_callback; -static std::set uic_mqtt_dotdot_aox_locator_force_read_attributes_callback; +static std::set uic_mqtt_dotdot_user_credential_add_user_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_add_user_callback; +static std::set uic_mqtt_dotdot_user_credential_modify_user_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_modify_user_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_user_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_user_callback; +static std::set uic_mqtt_dotdot_user_credential_add_credential_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_add_credential_callback; +static std::set uic_mqtt_dotdot_user_credential_modify_credential_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_modify_credential_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_credential_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_credential_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_all_users_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_all_credentials_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback; +static std::set uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback; +static std::set uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback; +static std::set uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback; +static std::set uic_mqtt_dotdot_user_credential_credential_learn_stop_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback; +static std::set uic_mqtt_dotdot_user_credential_credential_association_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_credential_association_callback; +static std::set uic_mqtt_dotdot_user_credential_get_user_checksum_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback; +static std::set uic_mqtt_dotdot_user_credential_get_credential_checksum_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback; +static std::set uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback; +static std::set uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback; +static std::set uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback; +static std::set uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback; +static std::set uic_mqtt_dotdot_user_credential_write_attributes_callback; +static std::set uic_mqtt_dotdot_user_credential_force_read_attributes_callback; // Callbacks setters -void uic_mqtt_dotdot_aox_locator_iq_report_callback_set(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_add_user_callback_set(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_iq_report_callback.insert(callback); + uic_mqtt_dotdot_user_credential_add_user_callback.insert(callback); } } -void uic_mqtt_dotdot_aox_locator_iq_report_callback_unset(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_add_user_callback_unset(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback) { - uic_mqtt_dotdot_aox_locator_iq_report_callback.erase(callback); + uic_mqtt_dotdot_user_credential_add_user_callback.erase(callback); } -void uic_mqtt_dotdot_aox_locator_iq_report_callback_clear() +void uic_mqtt_dotdot_user_credential_add_user_callback_clear() { - uic_mqtt_dotdot_aox_locator_iq_report_callback.clear(); + uic_mqtt_dotdot_user_credential_add_user_callback.clear(); } -std::set& get_uic_mqtt_dotdot_aox_locator_iq_report_callback() +std::set& get_uic_mqtt_dotdot_user_credential_add_user_callback() { - return uic_mqtt_dotdot_aox_locator_iq_report_callback; + return uic_mqtt_dotdot_user_credential_add_user_callback; } -void uic_mqtt_dotdot_aox_locator_generated_iq_report_callback_set(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_add_user_callback_set(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.insert(callback); + uic_mqtt_dotdot_user_credential_generated_add_user_callback.insert(callback); } } -void uic_mqtt_dotdot_aox_locator_generated_iq_report_callback_unset(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_add_user_callback_unset(const uic_mqtt_dotdot_user_credential_add_user_callback_t callback) { - uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.erase(callback); + uic_mqtt_dotdot_user_credential_generated_add_user_callback.erase(callback); } -void uic_mqtt_dotdot_aox_locator_generated_iq_report_callback_clear() +void uic_mqtt_dotdot_user_credential_generated_add_user_callback_clear() { - uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.clear(); + uic_mqtt_dotdot_user_credential_generated_add_user_callback.clear(); } -void uic_mqtt_dotdot_aox_locator_angle_report_callback_set(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_modify_user_callback_set(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_angle_report_callback.insert(callback); + uic_mqtt_dotdot_user_credential_modify_user_callback.insert(callback); } } -void uic_mqtt_dotdot_aox_locator_angle_report_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_modify_user_callback_unset(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback) { - uic_mqtt_dotdot_aox_locator_angle_report_callback.erase(callback); + uic_mqtt_dotdot_user_credential_modify_user_callback.erase(callback); } -void uic_mqtt_dotdot_aox_locator_angle_report_callback_clear() +void uic_mqtt_dotdot_user_credential_modify_user_callback_clear() { - uic_mqtt_dotdot_aox_locator_angle_report_callback.clear(); + uic_mqtt_dotdot_user_credential_modify_user_callback.clear(); } -std::set& get_uic_mqtt_dotdot_aox_locator_angle_report_callback() +std::set& get_uic_mqtt_dotdot_user_credential_modify_user_callback() { - return uic_mqtt_dotdot_aox_locator_angle_report_callback; + return uic_mqtt_dotdot_user_credential_modify_user_callback; } -void uic_mqtt_dotdot_aox_locator_generated_angle_report_callback_set(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_modify_user_callback_set(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.insert(callback); + uic_mqtt_dotdot_user_credential_generated_modify_user_callback.insert(callback); } } -void uic_mqtt_dotdot_aox_locator_generated_angle_report_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_modify_user_callback_unset(const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback) { - uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.erase(callback); + uic_mqtt_dotdot_user_credential_generated_modify_user_callback.erase(callback); } -void uic_mqtt_dotdot_aox_locator_generated_angle_report_callback_clear() +void uic_mqtt_dotdot_user_credential_generated_modify_user_callback_clear() { - uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.clear(); + uic_mqtt_dotdot_user_credential_generated_modify_user_callback.clear(); } -void uic_mqtt_dotdot_aox_locator_angle_correction_callback_set(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) +void uic_mqtt_dotdot_user_credential_delete_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_angle_correction_callback.insert(callback); + uic_mqtt_dotdot_user_credential_delete_user_callback.insert(callback); } } -void uic_mqtt_dotdot_aox_locator_angle_correction_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) +void uic_mqtt_dotdot_user_credential_delete_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback) { - uic_mqtt_dotdot_aox_locator_angle_correction_callback.erase(callback); + uic_mqtt_dotdot_user_credential_delete_user_callback.erase(callback); } -void uic_mqtt_dotdot_aox_locator_angle_correction_callback_clear() +void uic_mqtt_dotdot_user_credential_delete_user_callback_clear() { - uic_mqtt_dotdot_aox_locator_angle_correction_callback.clear(); + uic_mqtt_dotdot_user_credential_delete_user_callback.clear(); } -std::set& get_uic_mqtt_dotdot_aox_locator_angle_correction_callback() +std::set& get_uic_mqtt_dotdot_user_credential_delete_user_callback() { - return uic_mqtt_dotdot_aox_locator_angle_correction_callback; + return uic_mqtt_dotdot_user_credential_delete_user_callback; } -void uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback_set(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_delete_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.insert(callback); + uic_mqtt_dotdot_user_credential_generated_delete_user_callback.insert(callback); } } -void uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_delete_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback) { - uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.erase(callback); + uic_mqtt_dotdot_user_credential_generated_delete_user_callback.erase(callback); } -void uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback_clear() +void uic_mqtt_dotdot_user_credential_generated_delete_user_callback_clear() { - uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.clear(); + uic_mqtt_dotdot_user_credential_generated_delete_user_callback.clear(); } - -void uic_mqtt_dotdot_set_aox_locator_write_attributes_callback( - const uic_mqtt_dotdot_aox_locator_write_attributes_callback_t callback) +void uic_mqtt_dotdot_user_credential_add_credential_callback_set(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_write_attributes_callback.insert(callback); + uic_mqtt_dotdot_user_credential_add_credential_callback.insert(callback); } } -void uic_mqtt_dotdot_unset_aox_locator_write_attributes_callback( - const uic_mqtt_dotdot_aox_locator_write_attributes_callback_t callback) +void uic_mqtt_dotdot_user_credential_add_credential_callback_unset(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback) { - uic_mqtt_dotdot_aox_locator_write_attributes_callback.erase(callback); + uic_mqtt_dotdot_user_credential_add_credential_callback.erase(callback); } -void uic_mqtt_dotdot_clear_aox_locator_write_attributes_callbacks() +void uic_mqtt_dotdot_user_credential_add_credential_callback_clear() { - uic_mqtt_dotdot_aox_locator_write_attributes_callback.clear(); + uic_mqtt_dotdot_user_credential_add_credential_callback.clear(); } -std::set& get_uic_mqtt_dotdot_aox_locator_write_attributes_callback() +std::set& get_uic_mqtt_dotdot_user_credential_add_credential_callback() { - return uic_mqtt_dotdot_aox_locator_write_attributes_callback; + return uic_mqtt_dotdot_user_credential_add_credential_callback; } -void uic_mqtt_dotdot_set_aox_locator_force_read_attributes_callback( - const uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_add_credential_callback_set(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.insert(callback); + uic_mqtt_dotdot_user_credential_generated_add_credential_callback.insert(callback); } } -void uic_mqtt_dotdot_unset_aox_locator_force_read_attributes_callback( - const uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t callback) +void uic_mqtt_dotdot_user_credential_generated_add_credential_callback_unset(const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback) { - uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.erase(callback); + uic_mqtt_dotdot_user_credential_generated_add_credential_callback.erase(callback); } -void uic_mqtt_dotdot_clear_aox_locator_force_read_attributes_callbacks() +void uic_mqtt_dotdot_user_credential_generated_add_credential_callback_clear() { - uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.clear(); + uic_mqtt_dotdot_user_credential_generated_add_credential_callback.clear(); } - - -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/IQReport -void uic_mqtt_dotdot_on_aox_locator_iq_report( - const char *topic, - const char *message, - const size_t message_length) +void uic_mqtt_dotdot_user_credential_modify_credential_callback_set(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback) { - if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_iq_report_callback.empty())) { - return; + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_modify_credential_callback.insert(callback); } +} +void uic_mqtt_dotdot_user_credential_modify_credential_callback_unset(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_modify_credential_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_modify_credential_callback_clear() +{ + uic_mqtt_dotdot_user_credential_modify_credential_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_modify_credential_callback() +{ + return uic_mqtt_dotdot_user_credential_modify_credential_callback; +} - std::string unid; - uint8_t endpoint = 0; // Default value for endpoint-less topics. - if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { - sl_log_debug(LOG_TAG, - "Error parsing UNID / Endpoint ID from topic %s. Ignoring", - topic); - return; +void uic_mqtt_dotdot_user_credential_generated_modify_credential_callback_set(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_modify_credential_callback.insert(callback); } - - std::string tag_unid; - uint8_t channel = {}; - int8_t rssi = {}; - std::vector samples; - int32_t sequence = {}; - - - nlohmann::json jsn; - try { - jsn = nlohmann::json::parse(std::string(message)); - - - uic_mqtt_dotdot_parse_aox_locator_iq_report( - jsn, - tag_unid, - - channel, - - rssi, - - samples, - - sequence - ); - - } catch (const nlohmann::json::parse_error& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "IQReport"); - return; - } catch (const nlohmann::json::exception& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", e.what()); - return; - } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", ""); - return; +} +void uic_mqtt_dotdot_user_credential_generated_modify_credential_callback_unset(const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_modify_credential_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_modify_credential_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_modify_credential_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_delete_credential_callback_set(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_delete_credential_callback.insert(callback); } +} +void uic_mqtt_dotdot_user_credential_delete_credential_callback_unset(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_delete_credential_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_delete_credential_callback_clear() +{ + uic_mqtt_dotdot_user_credential_delete_credential_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_delete_credential_callback() +{ + return uic_mqtt_dotdot_user_credential_delete_credential_callback; +} - - - for (const auto& callback: uic_mqtt_dotdot_aox_locator_iq_report_callback){ - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - tag_unid.c_str(), - - channel, - - rssi, - - samples.size(), - samples.data(), - - sequence - - ); +void uic_mqtt_dotdot_user_credential_generated_delete_credential_callback_set(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_delete_credential_callback.insert(callback); } - } - -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/GeneratedCommands/IQReport -static void uic_mqtt_dotdot_on_generated_aox_locator_iq_report( - const char *topic, - const char *message, - const size_t message_length) +void uic_mqtt_dotdot_user_credential_generated_delete_credential_callback_unset(const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback) { - if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.empty())) { - return; + uic_mqtt_dotdot_user_credential_generated_delete_credential_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_delete_credential_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_delete_credential_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_delete_all_users_callback.insert(callback); } +} +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_delete_all_users_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_clear() +{ + uic_mqtt_dotdot_user_credential_delete_all_users_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_delete_all_users_callback() +{ + return uic_mqtt_dotdot_user_credential_delete_all_users_callback; +} - std::string unid; - uint8_t endpoint = 0; // Default value for endpoint-less topics. - if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { - sl_log_debug(LOG_TAG, - "Error parsing UNID / Endpoint ID from topic %s. Ignoring", - topic); - return; +void uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback.insert(callback); } +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_clear() +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback() +{ + return uic_mqtt_dotdot_user_credential_delete_all_credentials_callback; +} - std::string tag_unid; - uint8_t channel = {}; - int8_t rssi = {}; - std::vector samples; - int32_t sequence = {}; +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_clear() +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback() +{ + return uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback; +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_clear() +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback() +{ + return uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback; +} - nlohmann::json jsn; - try { - jsn = nlohmann::json::parse(std::string(message)); +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_clear() +{ + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback() +{ + return uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback; +} - - uic_mqtt_dotdot_parse_aox_locator_iq_report( - jsn, - tag_unid, +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback_set(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback_unset(const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_clear() +{ + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback() +{ + return uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback; +} - channel, +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_clear() +{ + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback() +{ + return uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback; +} - rssi, +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_clear() +{ + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback() +{ + return uic_mqtt_dotdot_user_credential_credential_learn_stop_callback; +} - samples, +void uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback_set(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback_unset(const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_credential_association_callback_set(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_credential_association_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_credential_association_callback_unset(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_credential_association_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_credential_association_callback_clear() +{ + uic_mqtt_dotdot_user_credential_credential_association_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_credential_association_callback() +{ + return uic_mqtt_dotdot_user_credential_credential_association_callback; +} - sequence - ); +void uic_mqtt_dotdot_user_credential_generated_credential_association_callback_set(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_credential_association_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_credential_association_callback_unset(const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_credential_association_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_credential_association_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_credential_association_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_get_user_checksum_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_get_user_checksum_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_clear() +{ + uic_mqtt_dotdot_user_credential_get_user_checksum_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_get_user_checksum_callback() +{ + return uic_mqtt_dotdot_user_credential_get_user_checksum_callback; +} - } catch (const nlohmann::json::parse_error& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "IQReport"); - return; - } catch (const nlohmann::json::exception& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", e.what()); - return; - } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", ""); - return; +void uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_clear() +{ + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback() +{ + return uic_mqtt_dotdot_user_credential_get_credential_checksum_callback; +} + +void uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback.insert(callback); } +} +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_clear() +{ + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback() +{ + return uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback; +} +void uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback_set(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback_unset(const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_clear() +{ + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback() +{ + return uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback; +} +void uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback.clear(); +} +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_clear() +{ + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback() +{ + return uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback; +} +void uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback.insert(callback); + } +} +void uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback_unset(const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback.erase(callback); +} +void uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback_clear() +{ + uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback.clear(); +} - for (const auto& callback: uic_mqtt_dotdot_aox_locator_generated_iq_report_callback){ - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - tag_unid.c_str(), - - channel, - - rssi, - - samples.size(), - samples.data(), +void uic_mqtt_dotdot_set_user_credential_write_attributes_callback( + const uic_mqtt_dotdot_user_credential_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_write_attributes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unset_user_credential_write_attributes_callback( + const uic_mqtt_dotdot_user_credential_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_user_credential_write_attributes_callbacks() +{ + uic_mqtt_dotdot_user_credential_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_user_credential_write_attributes_callback() +{ + return uic_mqtt_dotdot_user_credential_write_attributes_callback; +} - sequence - - ); +void uic_mqtt_dotdot_set_user_credential_force_read_attributes_callback( + const uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_user_credential_force_read_attributes_callback.insert(callback); } } +void uic_mqtt_dotdot_unset_user_credential_force_read_attributes_callback( + const uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_user_credential_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_user_credential_force_read_attributes_callback.clear(); +} -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/AngleReport -void uic_mqtt_dotdot_on_aox_locator_angle_report( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/AddUser +void uic_mqtt_dotdot_on_user_credential_add_user( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_angle_report_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_add_user_callback.empty())) { return; } @@ -92013,10 +92447,13 @@ void uic_mqtt_dotdot_on_aox_locator_angle_report( return; } - std::string tag_unid; - SphericalCoordinates direction = {}; - SphericalCoordinates deviation = {}; - int32_t sequence = {}; + uint16_t user_uniqueid = {}; + UserTypeEnum user_type = {}; + bool user_active_state = {}; + CredRule credential_rule = {}; + std::string user_name; + uint16_t expiring_timeout_minutes = {}; + UserNameEncodingType user_name_encoding = {}; nlohmann::json jsn; @@ -92024,57 +92461,69 @@ void uic_mqtt_dotdot_on_aox_locator_angle_report( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_angle_report( + uic_mqtt_dotdot_parse_user_credential_add_user( jsn, - tag_unid, + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence - ); + credential_rule, + + user_name, + + expiring_timeout_minutes, + + user_name_encoding + ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleReport"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "AddUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddUser", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_report_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_add_user_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - tag_unid.c_str(), + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name.c_str(), + + expiring_timeout_minutes, + + user_name_encoding ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/GeneratedCommands/AngleReport -static void uic_mqtt_dotdot_on_generated_aox_locator_angle_report( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/AddUser +static void uic_mqtt_dotdot_on_generated_user_credential_add_user( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_add_user_callback.empty())) { return; } @@ -92087,10 +92536,13 @@ static void uic_mqtt_dotdot_on_generated_aox_locator_angle_report( return; } - std::string tag_unid; - SphericalCoordinates direction = {}; - SphericalCoordinates deviation = {}; - int32_t sequence = {}; + uint16_t user_uniqueid = {}; + UserTypeEnum user_type = {}; + bool user_active_state = {}; + CredRule credential_rule = {}; + std::string user_name; + uint16_t expiring_timeout_minutes = {}; + UserNameEncodingType user_name_encoding = {}; nlohmann::json jsn; @@ -92098,58 +92550,70 @@ static void uic_mqtt_dotdot_on_generated_aox_locator_angle_report( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_angle_report( + uic_mqtt_dotdot_parse_user_credential_add_user( jsn, - tag_unid, + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name, + + expiring_timeout_minutes, + + user_name_encoding ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleReport"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "AddUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddUser", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_aox_locator_generated_angle_report_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_add_user_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - tag_unid.c_str(), + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name.c_str(), + + expiring_timeout_minutes, + + user_name_encoding ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/AngleCorrection -void uic_mqtt_dotdot_on_aox_locator_angle_correction( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/ModifyUser +void uic_mqtt_dotdot_on_user_credential_modify_user( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_angle_correction_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_modify_user_callback.empty())) { return; } @@ -92162,10 +92626,13 @@ void uic_mqtt_dotdot_on_aox_locator_angle_correction( return; } - std::string tag_unid; - SphericalCoordinates direction = {}; - SphericalCoordinates deviation = {}; - int32_t sequence = {}; + uint16_t user_uniqueid = {}; + UserTypeEnum user_type = {}; + bool user_active_state = {}; + CredRule credential_rule = {}; + std::string user_name; + uint16_t expiring_timeout_minutes = {}; + UserNameEncodingType user_name_encoding = {}; nlohmann::json jsn; @@ -92173,57 +92640,69 @@ void uic_mqtt_dotdot_on_aox_locator_angle_correction( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_angle_correction( + uic_mqtt_dotdot_parse_user_credential_modify_user( jsn, - tag_unid, + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name, + + expiring_timeout_minutes, + + user_name_encoding ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleCorrection"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "ModifyUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyUser", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_correction_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_modify_user_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - tag_unid.c_str(), + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name.c_str(), + + expiring_timeout_minutes, + + user_name_encoding ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/GeneratedCommands/AngleCorrection -static void uic_mqtt_dotdot_on_generated_aox_locator_angle_correction( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/ModifyUser +static void uic_mqtt_dotdot_on_generated_user_credential_modify_user( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_modify_user_callback.empty())) { return; } @@ -92236,10 +92715,13 @@ static void uic_mqtt_dotdot_on_generated_aox_locator_angle_correction( return; } - std::string tag_unid; - SphericalCoordinates direction = {}; - SphericalCoordinates deviation = {}; - int32_t sequence = {}; + uint16_t user_uniqueid = {}; + UserTypeEnum user_type = {}; + bool user_active_state = {}; + CredRule credential_rule = {}; + std::string user_name; + uint16_t expiring_timeout_minutes = {}; + UserNameEncodingType user_name_encoding = {}; nlohmann::json jsn; @@ -92247,62 +92729,70 @@ static void uic_mqtt_dotdot_on_generated_aox_locator_angle_correction( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_angle_correction( + uic_mqtt_dotdot_parse_user_credential_modify_user( jsn, - tag_unid, + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name, + + expiring_timeout_minutes, + + user_name_encoding ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleCorrection"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "ModifyUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyUser", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_modify_user_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - tag_unid.c_str(), + user_uniqueid, - direction, + user_type, - deviation, + user_active_state, - sequence + credential_rule, + + user_name.c_str(), + + expiring_timeout_minutes, + + user_name_encoding ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/WriteAttributes -void uic_mqtt_dotdot_on_aox_locator_WriteAttributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteUser +void uic_mqtt_dotdot_on_user_credential_delete_user( const char *topic, const char *message, const size_t message_length) { - if (uic_mqtt_dotdot_aox_locator_write_attributes_callback.empty()) { - return; - } - - if (message_length == 0) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_user_callback.empty())) { return; } @@ -92315,1546 +92805,1272 @@ void uic_mqtt_dotdot_on_aox_locator_WriteAttributes( return; } - uic_mqtt_dotdot_aox_locator_state_t new_state = {}; - uic_mqtt_dotdot_aox_locator_updated_state_t new_updated_state = {}; - - std::vector azimuth_mask; - - std::vector elevation_mask; - - std::vector allow_list; - - std::vector antenna_array; + uint16_t user_uniqueid = {}; nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_write_attributes( + + uic_mqtt_dotdot_parse_user_credential_delete_user( jsn, - new_state, - new_updated_state, - azimuth_mask, - elevation_mask, - allow_list, - antenna_array - ); + user_uniqueid + ); + } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "WriteAttributes"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "WriteAttributes", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "WriteAttributes", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteUser", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_aox_locator_write_attributes_callback){ + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_user_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - new_state, - new_updated_state + user_uniqueid + ); } } -static void uic_mqtt_dotdot_on_aox_locator_force_read_attributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteUser +static void uic_mqtt_dotdot_on_generated_user_credential_delete_user( const char *topic, const char *message, const size_t message_length) { - uint8_t endpoint = 0; - std::string unid; - - if ((message_length == 0) || (uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_user_callback.empty())) { return; } - if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } - try { - uic_mqtt_dotdot_aox_locator_updated_state_t force_update = {0}; - bool trigger_handler = false; + uint16_t user_uniqueid = {}; - nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - std::vector attributes = jsn["value"].get>(); - // Assume all attributes to be read on empty array received - if (attributes.size() == 0) { - force_update.reporting_mode = true; - force_update.position_and_orientation_valid = true; - force_update.position_and_orientation = true; - force_update.azimuth_mask = true; - force_update.elevation_mask = true; - force_update.allow_list = true; - force_update.aox_mode = true; - force_update.antenna_mode = true; - force_update.antenna_array = true; - force_update.period_samples = true; - force_update.angle_filtering = true; - force_update.angle_filtering_weight = true; - force_update.angle_correction_timeout = true; - force_update.angle_correction_delay = true; - force_update.cte_mode = true; - force_update.cte_sampling_interval = true; - force_update.cte_length = true; - force_update.slot_duration = true; - trigger_handler = true; - } else { - std::unordered_map supported_attrs = { - {"ReportingMode", &force_update.reporting_mode }, - {"PositionAndOrientationValid", &force_update.position_and_orientation_valid }, - {"PositionAndOrientation", &force_update.position_and_orientation }, - {"AzimuthMask", &force_update.azimuth_mask }, - {"ElevationMask", &force_update.elevation_mask }, - {"AllowList", &force_update.allow_list }, - {"AoXMode", &force_update.aox_mode }, - {"AntennaMode", &force_update.antenna_mode }, - {"AntennaArray", &force_update.antenna_array }, - {"PeriodSamples", &force_update.period_samples }, - {"AngleFiltering", &force_update.angle_filtering }, - {"AngleFilteringWeight", &force_update.angle_filtering_weight }, - {"AngleCorrectionTimeout", &force_update.angle_correction_timeout }, - {"AngleCorrectionDelay", &force_update.angle_correction_delay }, - {"CTEMode", &force_update.cte_mode }, - {"CTESamplingInterval", &force_update.cte_sampling_interval }, - {"CTELength", &force_update.cte_length }, - {"SlotDuration", &force_update.slot_duration }, - }; + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - for (auto& attribute : attributes) { - auto found_attr = supported_attrs.find(attribute); - if (found_attr != supported_attrs.end()) { - *(found_attr->second) = true; - trigger_handler = true; - } - } - } + + uic_mqtt_dotdot_parse_user_credential_delete_user( + jsn, + user_uniqueid + ); - if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_aox_locator_force_read_attributes_callback) { - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - force_update - ); - } - } - } catch (...) { - sl_log_debug(LOG_TAG, "AoXLocator/Commands/ForceReadAttributes: Unable to parse JSON payload"); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteUser"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteUser", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteUser", ""); return; } -} -sl_status_t uic_mqtt_dotdot_aox_locator_reporting_mode_publish( - const char *base_topic, - uint8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - // This is a single value - - #ifdef AOX_LOCATOR_REPORTING_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = aox_locator_reporting_mode_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_REPORTING_MODE. Using number instead."); - jsn["value"] = static_cast(value); - #endif - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); - } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/ReportingMode", e.what()); - return SL_STATUS_OK; + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_delete_user_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid + + ); } +} - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/ReportingMode"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/AddCredential +void uic_mqtt_dotdot_on_user_credential_add_credential( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_add_credential_callback.empty())) { + return; } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_reporting_mode_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/ReportingMode"; + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + std::string credential_data; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); - } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_valid_publish( - const char *base_topic, - bool value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a single value + + uic_mqtt_dotdot_parse_user_credential_add_credential( + jsn, + user_uniqueid, - if (true == uic_dotdot_has_attribute_value_a_name(64784,2,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,2,value); - }else{ - jsn["value"] = value; - } + credential_type, + credential_slot, - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + credential_data + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "AddCredential"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/PositionAndOrientationValid", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddCredential", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddCredential", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/PositionAndOrientationValid"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + for (const auto& callback: uic_mqtt_dotdot_user_credential_add_credential_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_data.c_str() + + ); } - return SL_STATUS_OK; + } -sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_valid_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/AddCredential +static void uic_mqtt_dotdot_on_generated_user_credential_add_credential( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/PositionAndOrientationValid"; - - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_add_credential_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_publish( - const char *base_topic, - CoordinateAndOrientation value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + std::string credential_data; + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a single value + + uic_mqtt_dotdot_parse_user_credential_add_credential( + jsn, + user_uniqueid, - nlohmann::json json_object = nlohmann::json::object(); - json_object["CoordinateX"] = value.CoordinateX; - json_object["CoordinateY"] = value.CoordinateY; - json_object["CoordinateZ"] = value.CoordinateZ; - json_object["OrientationX"] = value.OrientationX; - json_object["OrientationY"] = value.OrientationY; - json_object["OrientationZ"] = value.OrientationZ; - jsn["value"]= json_object; + credential_type, + credential_slot, - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + credential_data + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "AddCredential"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/PositionAndOrientation", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddCredential", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddCredential", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/PositionAndOrientation"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_add_credential_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_data.c_str() + + ); } - return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/PositionAndOrientation"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/ModifyCredential +void uic_mqtt_dotdot_on_user_credential_modify_credential( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_modify_credential_callback.empty())) { + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_azimuth_mask_publish( - const char *base_topic, - size_t value_count, - const MinMaxPair* value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + std::string credential_data; + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a variable size array of the same known type. - // Create an array under the value {"value":[]} - jsn["value"] = nlohmann::json::array(); + + uic_mqtt_dotdot_parse_user_credential_modify_credential( + jsn, + user_uniqueid, - for (size_t i = 0; i(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_data.c_str() + + ); } - return SL_STATUS_OK; + } -sl_status_t uic_mqtt_dotdot_aox_locator_azimuth_mask_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/ModifyCredential +static void uic_mqtt_dotdot_on_generated_user_credential_modify_credential( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AzimuthMask"; - - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_modify_credential_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_elevation_mask_publish( - const char *base_topic, - size_t value_count, - const MinMaxPair* value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + std::string credential_data; + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a variable size array of the same known type. - // Create an array under the value {"value":[]} - jsn["value"] = nlohmann::json::array(); + + uic_mqtt_dotdot_parse_user_credential_modify_credential( + jsn, + user_uniqueid, - for (size_t i = 0; i(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_data.c_str() + + ); } - return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_aox_locator_elevation_mask_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/ElevationMask"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteCredential +void uic_mqtt_dotdot_on_user_credential_delete_credential( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_credential_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_allow_list_publish( - const char *base_topic, - size_t value_count, - const char** value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a variable size array of the same known type. - // Create an array under the value {"value":[]} - jsn["value"] = nlohmann::json::array(); + + uic_mqtt_dotdot_parse_user_credential_delete_credential( + jsn, + user_uniqueid, - for (size_t i = 0; i(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot + + ); } +} - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AllowList"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteCredential +static void uic_mqtt_dotdot_on_generated_user_credential_delete_credential( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_credential_callback.empty())) { + return; } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_allow_list_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AllowList"; + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); - } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_aox_mode_publish( - const char *base_topic, - uint8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a single value + + uic_mqtt_dotdot_parse_user_credential_delete_credential( + jsn, + user_uniqueid, - #ifdef AOX_LOCATOR_AOX_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = aox_locator_aox_mode_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_AOX_MODE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + credential_type, + credential_slot + ); - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteCredential"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AoXMode", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteCredential", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteCredential", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AoXMode"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_aox_mode_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AoXMode"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_delete_credential_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot + + ); } - return SL_STATUS_OK; } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_antenna_mode_publish( - const char *base_topic, - uint8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) + +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteAllUsers +void uic_mqtt_dotdot_on_user_credential_delete_all_users( + const char *topic, + const char *message, + const size_t message_length) { - nlohmann::json jsn; + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_all_users_callback.empty())) { + return; + } - // This is a single value + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } - #ifdef AOX_LOCATOR_ANTENNA_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = aox_locator_antenna_mode_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_ANTENNA_MODE. Using number instead."); - jsn["value"] = static_cast(value); - #endif - std::string payload_str; + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllUsers"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AntennaMode", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllUsers", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllUsers", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AntennaMode"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} - -sl_status_t uic_mqtt_dotdot_aox_locator_antenna_mode_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AntennaMode"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_users_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } - return SL_STATUS_OK; + } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_antenna_array_publish( - const char *base_topic, - size_t value_count, - const int8_t* value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteAllUsers +static void uic_mqtt_dotdot_on_generated_user_credential_delete_all_users( + const char *topic, + const char *message, + const size_t message_length) { - nlohmann::json jsn; - - // This is a variable size array of the same known type. - // Create an array under the value {"value":[]} - jsn["value"] = nlohmann::json::array(); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback.empty())) { + return; + } - for (size_t i = 0; i(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } - return SL_STATUS_OK; } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_period_samples_publish( - const char *base_topic, - int8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - // This is a single value +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentials +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_all_credentials_callback.empty())) { + return; + } - if (true == uic_dotdot_has_attribute_value_a_name(64784,11,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,11,value); - }else{ - jsn["value"] = value; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - std::string payload_str; + + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentials"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/PeriodSamples", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentials", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentials", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/PeriodSamples"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} - -sl_status_t uic_mqtt_dotdot_aox_locator_period_samples_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/PeriodSamples"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } - return SL_STATUS_OK; + } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_angle_filtering_publish( - const char *base_topic, - bool value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteAllCredentials +static void uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials( + const char *topic, + const char *message, + const size_t message_length) { - nlohmann::json jsn; - - // This is a single value + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback.empty())) { + return; + } - if (true == uic_dotdot_has_attribute_value_a_name(64784,12,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,12,value); - }else{ - jsn["value"] = value; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - std::string payload_str; + + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentials"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleFiltering", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentials", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentials", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleFiltering"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_angle_filtering_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AngleFiltering"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } - return SL_STATUS_OK; } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_angle_filtering_weight_publish( - const char *base_topic, - double value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - // This is a single value +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentialsByType +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials_by_type( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback.empty())) { + return; + } - if (true == uic_dotdot_has_attribute_value_a_name(64784,13,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,13,value); - }else{ - jsn["value"] = value; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } + CredType credential_type = {}; - std::string payload_str; + + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); - } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleFilteringWeight", e.what()); - return SL_STATUS_OK; - } + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_by_type( + jsn, + credential_type + ); - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleFilteringWeight"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsByType"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsByType", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsByType", ""); + return; } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_angle_filtering_weight_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AngleFilteringWeight"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + credential_type + + ); } - return SL_STATUS_OK; + } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_timeout_publish( - const char *base_topic, - int8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteAllCredentialsByType +static void uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials_by_type( + const char *topic, + const char *message, + const size_t message_length) { - nlohmann::json jsn; - - // This is a single value + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback.empty())) { + return; + } - if (true == uic_dotdot_has_attribute_value_a_name(64784,14,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,14,value); - }else{ - jsn["value"] = value; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } + CredType credential_type = {}; - std::string payload_str; + + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_by_type( + jsn, + credential_type + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsByType"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleCorrectionTimeout", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsByType", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsByType", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleCorrectionTimeout"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_timeout_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AngleCorrectionTimeout"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + credential_type + + ); } - return SL_STATUS_OK; } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_delay_publish( - const char *base_topic, - int8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - // This is a single value +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentialsForUser +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback.empty())) { + return; + } - if (true == uic_dotdot_has_attribute_value_a_name(64784,15,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,15,value); - }else{ - jsn["value"] = value; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } + uint16_t user_uniqueid = {}; - std::string payload_str; + + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user( + jsn, + user_uniqueid + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsForUser"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleCorrectionDelay", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUser", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUser", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleCorrectionDelay"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid + + ); } - return SL_STATUS_OK; + } -sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_delay_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteAllCredentialsForUser +static void uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials_for_user( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/AngleCorrectionDelay"; - - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_cte_mode_publish( - const char *base_topic, - uint8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; + uint16_t user_uniqueid = {}; - // This is a single value - #ifdef AOX_LOCATOR_CTE_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = aox_locator_cte_mode_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_CTE_MODE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user( + jsn, + user_uniqueid + ); - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsForUser"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/CTEMode", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUser", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUser", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/CTEMode"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} -sl_status_t uic_mqtt_dotdot_aox_locator_cte_mode_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/CTEMode"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid + + ); } - return SL_STATUS_OK; } -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_cte_sampling_interval_publish( - const char *base_topic, - int8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - // This is a single value +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentialsForUserByType +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user_by_type( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback.empty())) { + return; + } - if (true == uic_dotdot_has_attribute_value_a_name(64784,17,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,17,value); - }else{ - jsn["value"] = value; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } + uint16_t user_uniqueid = {}; + CredType credential_type = {}; - std::string payload_str; + + nlohmann::json jsn; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user_by_type( + jsn, + user_uniqueid, + + credential_type + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsForUserByType"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/CTESamplingInterval", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUserByType", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUserByType", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/CTESamplingInterval"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type + + ); } - return SL_STATUS_OK; + } -sl_status_t uic_mqtt_dotdot_aox_locator_cte_sampling_interval_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType +static void uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials_for_user_by_type( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/CTESamplingInterval"; - - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_cte_length_publish( - const char *base_topic, - int8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; + uint16_t user_uniqueid = {}; + CredType credential_type = {}; - // This is a single value - if (true == uic_dotdot_has_attribute_value_a_name(64784,18,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,18,value); - }else{ - jsn["value"] = value; - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user_by_type( + jsn, + user_uniqueid, - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + credential_type + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsForUserByType"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/CTELength", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUserByType", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUserByType", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/CTELength"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type + + ); } - return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_aox_locator_cte_length_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/CTELength"; - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/CredentialLearnStartAdd +void uic_mqtt_dotdot_on_user_credential_credential_learn_start_add( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off -sl_status_t uic_mqtt_dotdot_aox_locator_slot_duration_publish( - const char *base_topic, - int8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + uint8_t credential_learn_timeout = {}; + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // This is a single value + + uic_mqtt_dotdot_parse_user_credential_credential_learn_start_add( + jsn, + user_uniqueid, - if (true == uic_dotdot_has_attribute_value_a_name(64784,19,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64784,19,value); - }else{ - jsn["value"] = value; - } + credential_type, + credential_slot, - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + credential_learn_timeout + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStartAdd"); + return; } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/SlotDuration", e.what()); - return SL_STATUS_OK; + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartAdd", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartAdd", ""); + return; } - std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/SlotDuration"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); + + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_learn_timeout + + ); } - return SL_STATUS_OK; + } -sl_status_t uic_mqtt_dotdot_aox_locator_slot_duration_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/CredentialLearnStartAdd +static void uic_mqtt_dotdot_on_generated_user_credential_credential_learn_start_add( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXLocator/Attributes/SlotDuration"; - - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + uint8_t credential_learn_timeout = {}; -sl_status_t uic_mqtt_dotdot_aox_locator_init() -{ - std::string base_topic = "ucl/by-unid/+/+/"; - std::string subscription_topic; - if(!uic_mqtt_dotdot_aox_locator_write_attributes_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_WriteAttributes); - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - if(!uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_force_read_attributes); - } - if (!uic_mqtt_dotdot_aox_locator_iq_report_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/Commands/IQReport"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_iq_report); - } - if (!uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/GeneratedCommands/IQReport"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_aox_locator_iq_report); - } - if (!uic_mqtt_dotdot_aox_locator_angle_report_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/Commands/AngleReport"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_angle_report); - } - if (!uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/GeneratedCommands/AngleReport"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_aox_locator_angle_report); - } - if (!uic_mqtt_dotdot_aox_locator_angle_correction_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/Commands/AngleCorrection"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_angle_correction); - } - if (!uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.empty()) { - subscription_topic = base_topic + "AoXLocator/GeneratedCommands/AngleCorrection"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_aox_locator_angle_correction); - } + + uic_mqtt_dotdot_parse_user_credential_credential_learn_start_add( + jsn, + user_uniqueid, - // Init the attributes for that cluster - uic_mqtt_dotdot_aox_locator_attributes_init(); + credential_type, - uic_mqtt_dotdot_by_group_aox_locator_init(); + credential_slot, - return SL_STATUS_OK; -} + credential_learn_timeout + ); -// Callbacks pointers -static std::set uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback; -static std::set uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback; + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStartAdd"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartAdd", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartAdd", ""); + return; + } -// Callbacks setters -void uic_mqtt_dotdot_set_aox_position_estimation_write_attributes_callback( - const uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.insert(callback); - } -} -void uic_mqtt_dotdot_unset_aox_position_estimation_write_attributes_callback( - const uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback_t callback) -{ - uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_aox_position_estimation_write_attributes_callbacks() -{ - uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback() -{ - return uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback; -} -void uic_mqtt_dotdot_set_aox_position_estimation_force_read_attributes_callback( - const uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.insert(callback); + + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_learn_timeout + + ); } } -void uic_mqtt_dotdot_unset_aox_position_estimation_force_read_attributes_callback( - const uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback_t callback) -{ - uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_aox_position_estimation_force_read_attributes_callbacks() -{ - uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.clear(); -} -// Callback function for incoming publications on ucl/by-unid/+/+/AoXPositionEstimation/Commands/WriteAttributes -void uic_mqtt_dotdot_on_aox_position_estimation_WriteAttributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/CredentialLearnStartModify +void uic_mqtt_dotdot_on_user_credential_credential_learn_start_modify( const char *topic, const char *message, const size_t message_length) { - if (uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.empty()) { - return; - } - - if (message_length == 0) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback.empty())) { return; } @@ -93867,298 +94083,151 @@ void uic_mqtt_dotdot_on_aox_position_estimation_WriteAttributes( return; } - uic_mqtt_dotdot_aox_position_estimation_state_t new_state = {}; - uic_mqtt_dotdot_aox_position_estimation_updated_state_t new_updated_state = {}; + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + uint8_t credential_learn_timeout = {}; nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_position_estimation_write_attributes( + + uic_mqtt_dotdot_parse_user_credential_credential_learn_start_modify( jsn, - new_state, - new_updated_state - ); + user_uniqueid, + + credential_type, + + credential_slot, + + credential_learn_timeout + ); + } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXPositionEstimation", "WriteAttributes"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStartModify"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXPositionEstimation", "WriteAttributes", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartModify", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXPositionEstimation", "WriteAttributes", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartModify", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback){ + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - new_state, - new_updated_state + user_uniqueid, + + credential_type, + + credential_slot, + + credential_learn_timeout + ); } } -static void uic_mqtt_dotdot_on_aox_position_estimation_force_read_attributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/CredentialLearnStartModify +static void uic_mqtt_dotdot_on_generated_user_credential_credential_learn_start_modify( const char *topic, const char *message, const size_t message_length) { - uint8_t endpoint = 0; - std::string unid; - - if ((message_length == 0) || (uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback.empty())) { return; } - if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } - try { - uic_mqtt_dotdot_aox_position_estimation_updated_state_t force_update = {0}; - bool trigger_handler = false; - - nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - std::vector attributes = jsn["value"].get>(); - - // Assume all attributes to be read on empty array received - if (attributes.size() == 0) { - force_update.position = true; - trigger_handler = true; - } else { - std::unordered_map supported_attrs = { - {"Position", &force_update.position }, - }; - - for (auto& attribute : attributes) { - auto found_attr = supported_attrs.find(attribute); - if (found_attr != supported_attrs.end()) { - *(found_attr->second) = true; - trigger_handler = true; - } - } - } + uint16_t user_uniqueid = {}; + CredType credential_type = {}; + uint16_t credential_slot = {}; + uint8_t credential_learn_timeout = {}; - if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback) { - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - force_update - ); - } - } - } catch (...) { - sl_log_debug(LOG_TAG, "AoXPositionEstimation/Commands/ForceReadAttributes: Unable to parse JSON payload"); - return; - } -} -sl_status_t uic_mqtt_dotdot_aox_position_estimation_position_publish( - const char *base_topic, - EstimatedPosition value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ nlohmann::json jsn; - - // This is a single value - - nlohmann::json json_object = nlohmann::json::object(); - json_object["ApplicationId"] = value.ApplicationId; - json_object["X"] = value.X; - json_object["Y"] = value.Y; - json_object["Z"] = value.Z; - json_object["DeviationX"] = value.DeviationX; - json_object["DeviationY"] = value.DeviationY; - json_object["DeviationZ"] = value.DeviationZ; - json_object["Sequence"] = value.Sequence; - jsn["value"]= json_object; - - - std::string payload_str; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); - } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXPositionEstimation/Attributes/Position", e.what()); - return SL_STATUS_OK; - } - - - std::string topic = std::string(base_topic) + "/AoXPositionEstimation/Attributes/Position"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} - -sl_status_t uic_mqtt_dotdot_aox_position_estimation_position_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/AoXPositionEstimation/Attributes/Position"; + jsn = nlohmann::json::parse(std::string(message)); - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); - } - return SL_STATUS_OK; -} -// clang-format off + + uic_mqtt_dotdot_parse_user_credential_credential_learn_start_modify( + jsn, + user_uniqueid, + credential_type, -sl_status_t uic_mqtt_dotdot_aox_position_estimation_init() -{ - std::string base_topic = "ucl/by-unid/+/+/"; + credential_slot, - std::string subscription_topic; - if(!uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.empty()) { - subscription_topic = base_topic + "AoXPositionEstimation/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_position_estimation_WriteAttributes); - } + credential_learn_timeout + ); - if(!uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "AoXPositionEstimation/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_position_estimation_force_read_attributes); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStartModify"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartModify", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartModify", ""); + return; } - // Init the attributes for that cluster - uic_mqtt_dotdot_aox_position_estimation_attributes_init(); - - uic_mqtt_dotdot_by_group_aox_position_estimation_init(); - - return SL_STATUS_OK; -} - -// Callbacks pointers -static std::set uic_mqtt_dotdot_protocol_controller_network_management_write_callback; -static std::set uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback; -static std::set uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback; -static std::set uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback; - -// Callbacks setters -void uic_mqtt_dotdot_protocol_controller_network_management_write_callback_set(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_protocol_controller_network_management_write_callback.insert(callback); - } -} -void uic_mqtt_dotdot_protocol_controller_network_management_write_callback_unset(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) -{ - uic_mqtt_dotdot_protocol_controller_network_management_write_callback.erase(callback); -} -void uic_mqtt_dotdot_protocol_controller_network_management_write_callback_clear() -{ - uic_mqtt_dotdot_protocol_controller_network_management_write_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_protocol_controller_network_management_write_callback() -{ - return uic_mqtt_dotdot_protocol_controller_network_management_write_callback; -} -void uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback_set(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.insert(callback); - } -} -void uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback_unset(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) -{ - uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.erase(callback); -} -void uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback_clear() -{ - uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.clear(); -} -void uic_mqtt_dotdot_set_protocol_controller_network_management_write_attributes_callback( - const uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.insert(callback); - } -} -void uic_mqtt_dotdot_unset_protocol_controller_network_management_write_attributes_callback( - const uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback_t callback) -{ - uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_protocol_controller_network_management_write_attributes_callbacks() -{ - uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback() -{ - return uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback; -} -void uic_mqtt_dotdot_set_protocol_controller_network_management_force_read_attributes_callback( - const uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.insert(callback); + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid, + + credential_type, + + credential_slot, + + credential_learn_timeout + + ); } } -void uic_mqtt_dotdot_unset_protocol_controller_network_management_force_read_attributes_callback( - const uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback_t callback) -{ - uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_protocol_controller_network_management_force_read_attributes_callbacks() -{ - uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.clear(); -} -// Callback function for incoming publications on ucl/by-unid/+/+/ProtocolController-NetworkManagement/Commands/Write -void uic_mqtt_dotdot_on_protocol_controller_network_management_write( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/CredentialLearnStop +void uic_mqtt_dotdot_on_user_credential_credential_learn_stop( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_protocol_controller_network_management_write_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_credential_learn_stop_callback.empty())) { return; } std::string unid; uint8_t endpoint = 0; // Default value for endpoint-less topics. - if(! uic_dotdot_mqtt::parse_topic_no_endpoint(topic,unid)) { + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, - "Error parsing UNID from topic %s. Ignoring", + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } @@ -94172,20 +94241,20 @@ void uic_mqtt_dotdot_on_protocol_controller_network_management_write( } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "ProtocolController-NetworkManagement", "Write"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStop"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStop", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStop", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_learn_stop_callback){ callback( static_cast(unid.c_str()), endpoint, @@ -94195,21 +94264,21 @@ void uic_mqtt_dotdot_on_protocol_controller_network_management_write( } -// Callback function for incoming publications on ucl/by-unid/+/+/ProtocolController-NetworkManagement/GeneratedCommands/Write -static void uic_mqtt_dotdot_on_generated_protocol_controller_network_management_write( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/CredentialLearnStop +static void uic_mqtt_dotdot_on_generated_user_credential_credential_learn_stop( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback.empty())) { return; } std::string unid; uint8_t endpoint = 0; // Default value for endpoint-less topics. - if(! uic_dotdot_mqtt::parse_topic_no_endpoint(topic,unid)) { + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, - "Error parsing UNID from topic %s. Ignoring", + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } @@ -94223,21 +94292,21 @@ static void uic_mqtt_dotdot_on_generated_protocol_controller_network_management_ } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "ProtocolController-NetworkManagement", "Write"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStop"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStop", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStop", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback){ callback( static_cast(unid.c_str()), endpoint, @@ -94247,285 +94316,172 @@ static void uic_mqtt_dotdot_on_generated_protocol_controller_network_management_ } -// Callback function for incoming publications on ucl/by-unid/+/+/ProtocolController-NetworkManagement/Commands/WriteAttributes -void uic_mqtt_dotdot_on_protocol_controller_network_management_WriteAttributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/CredentialAssociation +void uic_mqtt_dotdot_on_user_credential_credential_association( const char *topic, const char *message, const size_t message_length) { - if (uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.empty()) { - return; - } - - if (message_length == 0) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_credential_association_callback.empty())) { return; } std::string unid; uint8_t endpoint = 0; // Default value for endpoint-less topics. - if(! uic_dotdot_mqtt::parse_topic_no_endpoint(topic,unid)) { + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, - "Error parsing UNID from topic %s. Ignoring", + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } - uic_mqtt_dotdot_protocol_controller_network_management_state_t new_state = {}; - uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t new_updated_state = {}; + CredType credential_type = {}; + uint16_t source_user_uniqueid = {}; + uint16_t source_credential_slot = {}; + uint16_t destination_user_uniqueid = {}; + uint16_t destination_credential_slot = {}; nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_protocol_controller_network_management_write_attributes( + + uic_mqtt_dotdot_parse_user_credential_credential_association( jsn, - new_state, - new_updated_state - ); + credential_type, + + source_user_uniqueid, + + source_credential_slot, + + destination_user_uniqueid, + + destination_credential_slot + ); + } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "ProtocolController-NetworkManagement", "WriteAttributes"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialAssociation"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "WriteAttributes", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialAssociation", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "WriteAttributes", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialAssociation", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback){ + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_association_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - new_state, - new_updated_state + credential_type, + + source_user_uniqueid, + + source_credential_slot, + + destination_user_uniqueid, + + destination_credential_slot + ); } } -static void uic_mqtt_dotdot_on_protocol_controller_network_management_force_read_attributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/CredentialAssociation +static void uic_mqtt_dotdot_on_generated_user_credential_credential_association( const char *topic, const char *message, const size_t message_length) { - uint8_t endpoint = 0; - std::string unid; - - if ((message_length == 0) || (uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_credential_association_callback.empty())) { return; } - if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } - try { - uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t force_update = {0}; - bool trigger_handler = false; - - nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - std::vector attributes = jsn["value"].get>(); - - // Assume all attributes to be read on empty array received - if (attributes.size() == 0) { - force_update.network_management_state = true; - trigger_handler = true; - } else { - std::unordered_map supported_attrs = { - {"NetworkManagementState", &force_update.network_management_state }, - }; - - for (auto& attribute : attributes) { - auto found_attr = supported_attrs.find(attribute); - if (found_attr != supported_attrs.end()) { - *(found_attr->second) = true; - trigger_handler = true; - } - } - } + CredType credential_type = {}; + uint16_t source_user_uniqueid = {}; + uint16_t source_credential_slot = {}; + uint16_t destination_user_uniqueid = {}; + uint16_t destination_credential_slot = {}; - if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback) { - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - force_update - ); - } - } - } catch (...) { - sl_log_debug(LOG_TAG, "ProtocolController-NetworkManagement/Commands/ForceReadAttributes: Unable to parse JSON payload"); - return; - } -} -sl_status_t uic_mqtt_dotdot_protocol_controller_network_management_network_management_state_publish( - const char *base_topic, - NetworkManagementState value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ nlohmann::json jsn; - - // This is a single value - - nlohmann::json json_object = nlohmann::json::object(); - json_object["State"] = value.State; - json_object["SupportedStateList"] = value.SupportedStateList; - json_object["StateParameters"] = value.StateParameters; - json_object["RequestedStateParameters"] = value.RequestedStateParameters; - jsn["value"]= json_object; - - - std::string payload_str; try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); - } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController/NetworkManagement/Attributes/NetworkManagementState", e.what()); - return SL_STATUS_OK; - } - - - std::string topic = std::string(base_topic) + "/ProtocolController/NetworkManagement/Attributes/NetworkManagementState"; - if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) - { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) - { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } - return SL_STATUS_OK; -} + jsn = nlohmann::json::parse(std::string(message)); -sl_status_t uic_mqtt_dotdot_protocol_controller_network_management_network_management_state_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) -{ - // clang-format on - std::string topic - = std::string(base_topic) - + "/ProtocolController/NetworkManagement/Attributes/NetworkManagementState"; + + uic_mqtt_dotdot_parse_user_credential_credential_association( + jsn, + credential_type, - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); - } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); - } - return SL_STATUS_OK; -} -// clang-format off + source_user_uniqueid, + source_credential_slot, -sl_status_t uic_mqtt_dotdot_protocol_controller_network_management_init() -{ - std::string base_topic = "ucl/by-unid/+/"; + destination_user_uniqueid, - std::string subscription_topic; - if(!uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.empty()) { - subscription_topic = base_topic + "ProtocolController/NetworkManagement/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_protocol_controller_network_management_WriteAttributes); - } + destination_credential_slot + ); - if(!uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "ProtocolController/NetworkManagement/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_protocol_controller_network_management_force_read_attributes); - } - if (!uic_mqtt_dotdot_protocol_controller_network_management_write_callback.empty()) { - subscription_topic = base_topic + "ProtocolController/NetworkManagement/Commands/Write"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_protocol_controller_network_management_write); - } - if (!uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.empty()) { - subscription_topic = base_topic + "ProtocolController/NetworkManagement/GeneratedCommands/Write"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_protocol_controller_network_management_write); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialAssociation"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialAssociation", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialAssociation", ""); + return; } - // Init the attributes for that cluster - uic_mqtt_dotdot_protocol_controller_network_management_attributes_init(); - - return SL_STATUS_OK; -} - -// Callbacks pointers -static std::set uic_mqtt_dotdot_descriptor_write_attributes_callback; -static std::set uic_mqtt_dotdot_descriptor_force_read_attributes_callback; - -// Callbacks setters -void uic_mqtt_dotdot_set_descriptor_write_attributes_callback( - const uic_mqtt_dotdot_descriptor_write_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_descriptor_write_attributes_callback.insert(callback); - } -} -void uic_mqtt_dotdot_unset_descriptor_write_attributes_callback( - const uic_mqtt_dotdot_descriptor_write_attributes_callback_t callback) -{ - uic_mqtt_dotdot_descriptor_write_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_descriptor_write_attributes_callbacks() -{ - uic_mqtt_dotdot_descriptor_write_attributes_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_descriptor_write_attributes_callback() -{ - return uic_mqtt_dotdot_descriptor_write_attributes_callback; -} -void uic_mqtt_dotdot_set_descriptor_force_read_attributes_callback( - const uic_mqtt_dotdot_descriptor_force_read_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_descriptor_force_read_attributes_callback.insert(callback); + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_credential_association_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + credential_type, + + source_user_uniqueid, + + source_credential_slot, + + destination_user_uniqueid, + + destination_credential_slot + + ); } } -void uic_mqtt_dotdot_unset_descriptor_force_read_attributes_callback( - const uic_mqtt_dotdot_descriptor_force_read_attributes_callback_t callback) -{ - uic_mqtt_dotdot_descriptor_force_read_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_descriptor_force_read_attributes_callbacks() -{ - uic_mqtt_dotdot_descriptor_force_read_attributes_callback.clear(); -} -// Callback function for incoming publications on ucl/by-unid/+/+/Descriptor/Commands/WriteAttributes -void uic_mqtt_dotdot_on_descriptor_WriteAttributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/GetUserChecksum +void uic_mqtt_dotdot_on_user_credential_get_user_checksum( const char *topic, const char *message, const size_t message_length) { - if (uic_mqtt_dotdot_descriptor_write_attributes_callback.empty()) { - return; - } - - if (message_length == 0) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_get_user_checksum_callback.empty())) { return; } @@ -94538,326 +94494,335 @@ void uic_mqtt_dotdot_on_descriptor_WriteAttributes( return; } - uic_mqtt_dotdot_descriptor_state_t new_state = {}; - uic_mqtt_dotdot_descriptor_updated_state_t new_updated_state = {}; + uint16_t user_uniqueid = {}; nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_descriptor_write_attributes( + + uic_mqtt_dotdot_parse_user_credential_get_user_checksum( jsn, - new_state, - new_updated_state - ); + user_uniqueid + ); + } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "Descriptor", "WriteAttributes"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetUserChecksum"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "Descriptor", "WriteAttributes", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetUserChecksum", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "Descriptor", "WriteAttributes", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetUserChecksum", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_descriptor_write_attributes_callback){ + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_get_user_checksum_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - new_state, - new_updated_state + user_uniqueid + ); } } -static void uic_mqtt_dotdot_on_descriptor_force_read_attributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/GetUserChecksum +static void uic_mqtt_dotdot_on_generated_user_credential_get_user_checksum( const char *topic, const char *message, const size_t message_length) { - uint8_t endpoint = 0; - std::string unid; - - if ((message_length == 0) || (uic_mqtt_dotdot_descriptor_force_read_attributes_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback.empty())) { return; } - if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { sl_log_debug(LOG_TAG, "Error parsing UNID / Endpoint ID from topic %s. Ignoring", topic); return; } - try { - uic_mqtt_dotdot_descriptor_updated_state_t force_update = {0}; - bool trigger_handler = false; + uint16_t user_uniqueid = {}; - nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - std::vector attributes = jsn["value"].get>(); - // Assume all attributes to be read on empty array received - if (attributes.size() == 0) { - force_update.device_type_list = true; - trigger_handler = true; - } else { - std::unordered_map supported_attrs = { - {"DeviceTypeList", &force_update.device_type_list }, - }; + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - for (auto& attribute : attributes) { - auto found_attr = supported_attrs.find(attribute); - if (found_attr != supported_attrs.end()) { - *(found_attr->second) = true; - trigger_handler = true; - } - } - } + + uic_mqtt_dotdot_parse_user_credential_get_user_checksum( + jsn, + user_uniqueid + ); - if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_descriptor_force_read_attributes_callback) { - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - force_update - ); - } - } - } catch (...) { - sl_log_debug(LOG_TAG, "Descriptor/Commands/ForceReadAttributes: Unable to parse JSON payload"); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetUserChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetUserChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetUserChecksum", ""); return; } + + + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + user_uniqueid + + ); + } } -sl_status_t uic_mqtt_dotdot_descriptor_device_type_list_publish( - const char *base_topic, - size_t value_count, - const DeviceTypeStruct* value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - // This is a variable size array of the same known type. - // Create an array under the value {"value":[]} - jsn["value"] = nlohmann::json::array(); +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/GetCredentialChecksum +void uic_mqtt_dotdot_on_user_credential_get_credential_checksum( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_get_credential_checksum_callback.empty())) { + return; + } - for (size_t i = 0; i(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + credential_type + + ); } - return SL_STATUS_OK; + } -sl_status_t uic_mqtt_dotdot_descriptor_device_type_list_unretain( - const char *base_topic, - uic_mqtt_dotdot_attribute_publish_type_t publish_type) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/GetCredentialChecksum +static void uic_mqtt_dotdot_on_generated_user_credential_get_credential_checksum( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string topic - = std::string(base_topic) - + "/Descriptor/Attributes/DeviceTypeList"; - - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_desired = topic + "/Desired"; - uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback.empty())) { + return; } - if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) - || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { - std::string topic_reported = topic + "/Reported"; - uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return SL_STATUS_OK; -} -// clang-format off + CredType credential_type = {}; -sl_status_t uic_mqtt_dotdot_descriptor_init() -{ - std::string base_topic = "ucl/by-unid/+/+/"; - std::string subscription_topic; - if(!uic_mqtt_dotdot_descriptor_write_attributes_callback.empty()) { - subscription_topic = base_topic + "Descriptor/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_descriptor_WriteAttributes); - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - if(!uic_mqtt_dotdot_descriptor_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "Descriptor/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_descriptor_force_read_attributes); + + uic_mqtt_dotdot_parse_user_credential_get_credential_checksum( + jsn, + credential_type + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetCredentialChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetCredentialChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetCredentialChecksum", ""); + return; } - // Init the attributes for that cluster - uic_mqtt_dotdot_descriptor_attributes_init(); - uic_mqtt_dotdot_by_group_descriptor_init(); - return SL_STATUS_OK; + + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + credential_type + + ); + } } -// Callbacks pointers -static std::set uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback; -static std::set uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback; -static std::set uic_mqtt_dotdot_unify_fan_control_turn_off_callback; -static std::set uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback; -static std::set uic_mqtt_dotdot_unify_fan_control_write_attributes_callback; -static std::set uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback; -// Callbacks setters -void uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_set(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/GetAllUsersChecksum +void uic_mqtt_dotdot_on_user_credential_get_all_users_checksum( + const char *topic, + const char *message, + const size_t message_length) { - if (callback != nullptr) { - uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.insert(callback); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback.empty())) { + return; } -} -void uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_unset(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) -{ - uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.erase(callback); -} -void uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_clear() -{ - uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback() -{ - return uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback; -} -void uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback_set(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.insert(callback); + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } -} -void uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback_unset(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) -{ - uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.erase(callback); -} -void uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback_clear() -{ - uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.clear(); -} -void uic_mqtt_dotdot_unify_fan_control_turn_off_callback_set(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_unify_fan_control_turn_off_callback.insert(callback); + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetAllUsersChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetAllUsersChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetAllUsersChecksum", ""); + return; } -} -void uic_mqtt_dotdot_unify_fan_control_turn_off_callback_unset(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) -{ - uic_mqtt_dotdot_unify_fan_control_turn_off_callback.erase(callback); -} -void uic_mqtt_dotdot_unify_fan_control_turn_off_callback_clear() -{ - uic_mqtt_dotdot_unify_fan_control_turn_off_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_unify_fan_control_turn_off_callback() -{ - return uic_mqtt_dotdot_unify_fan_control_turn_off_callback; -} -void uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback_set(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.insert(callback); + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } -} -void uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback_unset(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) -{ - uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.erase(callback); -} -void uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback_clear() -{ - uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.clear(); + } -void uic_mqtt_dotdot_set_unify_fan_control_write_attributes_callback( - const uic_mqtt_dotdot_unify_fan_control_write_attributes_callback_t callback) +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/GetAllUsersChecksum +static void uic_mqtt_dotdot_on_generated_user_credential_get_all_users_checksum( + const char *topic, + const char *message, + const size_t message_length) { - if (callback != nullptr) { - uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.insert(callback); + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback.empty())) { + return; } -} -void uic_mqtt_dotdot_unset_unify_fan_control_write_attributes_callback( - const uic_mqtt_dotdot_unify_fan_control_write_attributes_callback_t callback) -{ - uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_unify_fan_control_write_attributes_callbacks() -{ - uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_unify_fan_control_write_attributes_callback() -{ - return uic_mqtt_dotdot_unify_fan_control_write_attributes_callback; -} -void uic_mqtt_dotdot_set_unify_fan_control_force_read_attributes_callback( - const uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.insert(callback); + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetAllUsersChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetAllUsersChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetAllUsersChecksum", ""); + return; + } + + + + + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } -} -void uic_mqtt_dotdot_unset_unify_fan_control_force_read_attributes_callback( - const uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback_t callback) -{ - uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_unify_fan_control_force_read_attributes_callbacks() -{ - uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.clear(); } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/Commands/SetFanMode -void uic_mqtt_dotdot_on_unify_fan_control_set_fan_mode( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/SetAdminPINCode +void uic_mqtt_dotdot_on_user_credential_set_admin_pin_code( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback.empty())) { return; } @@ -94870,7 +94835,7 @@ void uic_mqtt_dotdot_on_unify_fan_control_set_fan_mode( return; } - ZWaveFanModeEnum fan_mode = {}; + std::string pin_code; nlohmann::json jsn; @@ -94878,45 +94843,45 @@ void uic_mqtt_dotdot_on_unify_fan_control_set_fan_mode( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_fan_control_set_fan_mode( + uic_mqtt_dotdot_parse_user_credential_set_admin_pin_code( jsn, - fan_mode + pin_code ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "SetFanMode"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "SetAdminPINCode"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "SetAdminPINCode", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "SetAdminPINCode", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - fan_mode + pin_code.c_str() ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/GeneratedCommands/SetFanMode -static void uic_mqtt_dotdot_on_generated_unify_fan_control_set_fan_mode( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/SetAdminPINCode +static void uic_mqtt_dotdot_on_generated_user_credential_set_admin_pin_code( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback.empty())) { return; } @@ -94929,7 +94894,7 @@ static void uic_mqtt_dotdot_on_generated_unify_fan_control_set_fan_mode( return; } - ZWaveFanModeEnum fan_mode = {}; + std::string pin_code; nlohmann::json jsn; @@ -94937,46 +94902,46 @@ static void uic_mqtt_dotdot_on_generated_unify_fan_control_set_fan_mode( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_fan_control_set_fan_mode( + uic_mqtt_dotdot_parse_user_credential_set_admin_pin_code( jsn, - fan_mode + pin_code ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "SetFanMode"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "SetAdminPINCode"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "SetAdminPINCode", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "SetAdminPINCode", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - fan_mode + pin_code.c_str() ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/Commands/TurnOff -void uic_mqtt_dotdot_on_unify_fan_control_turn_off( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/DeactivateAdminPINCode +void uic_mqtt_dotdot_on_user_credential_deactivate_admin_pin_code( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_turn_off_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback.empty())) { return; } @@ -94998,20 +94963,20 @@ void uic_mqtt_dotdot_on_unify_fan_control_turn_off( } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "TurnOff"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeactivateAdminPINCode"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeactivateAdminPINCode", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeactivateAdminPINCode", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_turn_off_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback){ callback( static_cast(unid.c_str()), endpoint, @@ -95021,13 +94986,13 @@ void uic_mqtt_dotdot_on_unify_fan_control_turn_off( } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/GeneratedCommands/TurnOff -static void uic_mqtt_dotdot_on_generated_unify_fan_control_turn_off( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/GeneratedCommands/DeactivateAdminPINCode +static void uic_mqtt_dotdot_on_generated_user_credential_deactivate_admin_pin_code( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback.empty())) { return; } @@ -95049,21 +95014,21 @@ static void uic_mqtt_dotdot_on_generated_unify_fan_control_turn_off( } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "TurnOff"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeactivateAdminPINCode"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeactivateAdminPINCode", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeactivateAdminPINCode", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback){ callback( static_cast(unid.c_str()), endpoint, @@ -95073,13 +95038,13 @@ static void uic_mqtt_dotdot_on_generated_unify_fan_control_turn_off( } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/Commands/WriteAttributes -void uic_mqtt_dotdot_on_unify_fan_control_WriteAttributes( +// Callback function for incoming publications on ucl/by-unid/+/+/UserCredential/Commands/WriteAttributes +void uic_mqtt_dotdot_on_user_credential_WriteAttributes( const char *topic, const char *message, const size_t message_length) { - if (uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.empty()) { + if (uic_mqtt_dotdot_user_credential_write_attributes_callback.empty()) { return; } @@ -95096,33 +95061,33 @@ void uic_mqtt_dotdot_on_unify_fan_control_WriteAttributes( return; } - uic_mqtt_dotdot_unify_fan_control_state_t new_state = {}; - uic_mqtt_dotdot_unify_fan_control_updated_state_t new_updated_state = {}; + uic_mqtt_dotdot_user_credential_state_t new_state = {}; + uic_mqtt_dotdot_user_credential_updated_state_t new_updated_state = {}; nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_fan_control_write_attributes( + uic_mqtt_dotdot_parse_user_credential_write_attributes( jsn, new_state, new_updated_state ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "WriteAttributes"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "WriteAttributes"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "WriteAttributes", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "WriteAttributes", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "WriteAttributes", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "WriteAttributes", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_write_attributes_callback){ + for (const auto& callback: uic_mqtt_dotdot_user_credential_write_attributes_callback){ callback( static_cast(unid.c_str()), endpoint, @@ -95134,7 +95099,7 @@ void uic_mqtt_dotdot_on_unify_fan_control_WriteAttributes( } -static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( +static void uic_mqtt_dotdot_on_user_credential_force_read_attributes( const char *topic, const char *message, const size_t message_length) @@ -95142,7 +95107,7 @@ static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( uint8_t endpoint = 0; std::string unid; - if ((message_length == 0) || (uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.empty())) { + if ((message_length == 0) || (uic_mqtt_dotdot_user_credential_force_read_attributes_callback.empty())) { return; } @@ -95154,7 +95119,7 @@ static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( } try { - uic_mqtt_dotdot_unify_fan_control_updated_state_t force_update = {0}; + uic_mqtt_dotdot_user_credential_updated_state_t force_update = {0}; bool trigger_handler = false; nlohmann::json jsn = nlohmann::json::parse(std::string(message)); @@ -95162,15 +95127,25 @@ static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( // Assume all attributes to be read on empty array received if (attributes.size() == 0) { - force_update.z_wave_fan_mode = true; - force_update.z_wave_supported_fan_mode = true; - force_update.z_wave_fan_state = true; + force_update.supported_user_unique_identifiers = true; + force_update.supported_credential_rules = true; + force_update.supported_credential_types = true; + force_update.supported_user_types = true; + force_update.support_credential_checksum = true; + force_update.support_admin_pin_code = true; + force_update.support_admin_pin_code_deactivation = true; + force_update.admin_pin_code = true; trigger_handler = true; } else { std::unordered_map supported_attrs = { - {"ZWaveFanMode", &force_update.z_wave_fan_mode }, - {"ZWaveSupportedFanMode", &force_update.z_wave_supported_fan_mode }, - {"ZWaveFanState", &force_update.z_wave_fan_state }, + {"SupportedUserUniqueIdentifiers", &force_update.supported_user_unique_identifiers }, + {"SupportedCredentialRules", &force_update.supported_credential_rules }, + {"SupportedCredentialTypes", &force_update.supported_credential_types }, + {"SupportedUserTypes", &force_update.supported_user_types }, + {"SupportCredentialChecksum", &force_update.support_credential_checksum }, + {"SupportAdminPinCode", &force_update.support_admin_pin_code }, + {"SupportAdminPinCodeDeactivation", &force_update.support_admin_pin_code_deactivation }, + {"AdminPinCode", &force_update.admin_pin_code }, }; for (auto& attribute : attributes) { @@ -95183,7 +95158,7 @@ static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( } if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback) { + for (const auto& callback: uic_mqtt_dotdot_user_credential_force_read_attributes_callback) { callback( static_cast(unid.c_str()), endpoint, @@ -95193,14 +95168,14 @@ static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( } } } catch (...) { - sl_log_debug(LOG_TAG, "UnifyFanControl/Commands/ForceReadAttributes: Unable to parse JSON payload"); + sl_log_debug(LOG_TAG, "UserCredential/Commands/ForceReadAttributes: Unable to parse JSON payload"); return; } } -sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_publish( +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_publish( const char *base_topic, - ZWaveFanModeEnum value, + uint16_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -95208,14 +95183,11 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_publish( // This is a single value - #ifdef UNIFY_FAN_CONTROL_Z_WAVE_FAN_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_fan_control_z_wave_fan_mode_get_enum_value_name((uint32_t)value); - #elif defined(Z_WAVE_FAN_MODE_ENUM_ENUM_NAME_AVAILABLE) - jsn["value"] = z_wave_fan_mode_enum_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_FAN_CONTROL_Z_WAVE_FAN_MODE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + if (true == uic_dotdot_has_attribute_value_a_name(64776,0,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64776,0,value); + }else{ + jsn["value"] = value; + } std::string payload_str; @@ -95223,12 +95195,12 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl/Attributes/ZWaveFanMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportedUserUniqueIdentifiers", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ZWaveFanMode"; + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportedUserUniqueIdentifiers"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -95248,14 +95220,14 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_unretain( +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyFanControl/Attributes/ZWaveFanMode"; + + "/UserCredential/Attributes/SupportedUserUniqueIdentifiers"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -95271,9 +95243,9 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_publish( +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_rules_publish( const char *base_topic, - uint16_t value, + uint8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -95281,7 +95253,7 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_publish( // This is a single value - nlohmann::json bitmap_values = UnifyFanControlZWaveSupportedFanMode.get_bitmap_values_as_json_tree((uint32_t)value); + nlohmann::json bitmap_values = UserCredentialSupportedCredentialRules.get_bitmap_values_as_json_tree((uint32_t)value); jsn["value"] = bitmap_values; @@ -95290,14 +95262,14 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl/Attributes/ZWaveSupportedFanMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportedCredentialRules", e.what()); return SL_STATUS_OK; } boost::replace_all(payload_str, "\"true\"", "true"); boost::replace_all(payload_str, "\"false\"", "false"); - std::string topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ZWaveSupportedFanMode"; + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportedCredentialRules"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -95317,14 +95289,14 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_unretain( +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_rules_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyFanControl/Attributes/ZWaveSupportedFanMode"; + + "/UserCredential/Attributes/SupportedCredentialRules"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -95340,9 +95312,9 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_unretain } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_publish( +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_types_publish( const char *base_topic, - ZWaveFanStateEnum value, + uint16_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -95350,14 +95322,8 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_publish( // This is a single value - #ifdef UNIFY_FAN_CONTROL_Z_WAVE_FAN_STATE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_fan_control_z_wave_fan_state_get_enum_value_name((uint32_t)value); - #elif defined(Z_WAVE_FAN_STATE_ENUM_ENUM_NAME_AVAILABLE) - jsn["value"] = z_wave_fan_state_enum_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_FAN_CONTROL_Z_WAVE_FAN_STATE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + nlohmann::json bitmap_values = UserCredentialSupportedCredentialTypes.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; std::string payload_str; @@ -95365,12 +95331,14 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl/Attributes/ZWaveFanState", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportedCredentialTypes", e.what()); return SL_STATUS_OK; } + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); - std::string topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ZWaveFanState"; + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportedCredentialTypes"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -95390,14 +95358,14 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_unretain( +sl_status_t uic_mqtt_dotdot_user_credential_supported_credential_types_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyFanControl/Attributes/ZWaveFanState"; + + "/UserCredential/Attributes/SupportedCredentialTypes"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -95413,247 +95381,33 @@ sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_unretain( } // clang-format off - -sl_status_t uic_mqtt_dotdot_unify_fan_control_init() +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_types_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - std::string base_topic = "ucl/by-unid/+/+/"; + nlohmann::json jsn; - std::string subscription_topic; - if(!uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.empty()) { - subscription_topic = base_topic + "UnifyFanControl/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_WriteAttributes); - } + // This is a single value - if(!uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "UnifyFanControl/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes); - } - if (!uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.empty()) { - subscription_topic = base_topic + "UnifyFanControl/Commands/SetFanMode"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_set_fan_mode); - } - if (!uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.empty()) { - subscription_topic = base_topic + "UnifyFanControl/GeneratedCommands/SetFanMode"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_fan_control_set_fan_mode); - } - if (!uic_mqtt_dotdot_unify_fan_control_turn_off_callback.empty()) { - subscription_topic = base_topic + "UnifyFanControl/Commands/TurnOff"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_turn_off); - } - if (!uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.empty()) { - subscription_topic = base_topic + "UnifyFanControl/GeneratedCommands/TurnOff"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_fan_control_turn_off); - } - - // Init the attributes for that cluster - uic_mqtt_dotdot_unify_fan_control_attributes_init(); - - uic_mqtt_dotdot_by_group_unify_fan_control_init(); - - return SL_STATUS_OK; -} - -// Callbacks pointers -static std::set uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; -static std::set uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback; - -// Callbacks setters - -void uic_mqtt_dotdot_set_unify_thermostat_write_attributes_callback( - const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.insert(callback); - } -} -void uic_mqtt_dotdot_unset_unify_thermostat_write_attributes_callback( - const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback) -{ - uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_unify_thermostat_write_attributes_callbacks() -{ - uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.clear(); -} -std::set& get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback() -{ - return uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; -} - -void uic_mqtt_dotdot_set_unify_thermostat_force_read_attributes_callback( - const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback) -{ - if (callback != nullptr) { - uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.insert(callback); - } -} -void uic_mqtt_dotdot_unset_unify_thermostat_force_read_attributes_callback( - const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback) -{ - uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.erase(callback); -} -void uic_mqtt_dotdot_clear_unify_thermostat_force_read_attributes_callbacks() -{ - uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.clear(); -} - - -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyThermostat/Commands/WriteAttributes -void uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes( - const char *topic, - const char *message, - const size_t message_length) -{ - if (uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.empty()) { - return; - } - - if (message_length == 0) { - return; - } - - std::string unid; - uint8_t endpoint = 0; // Default value for endpoint-less topics. - if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { - sl_log_debug(LOG_TAG, - "Error parsing UNID / Endpoint ID from topic %s. Ignoring", - topic); - return; - } - - uic_mqtt_dotdot_unify_thermostat_state_t new_state = {}; - uic_mqtt_dotdot_unify_thermostat_updated_state_t new_updated_state = {}; - - - nlohmann::json jsn; - try { - jsn = nlohmann::json::parse(std::string(message)); - - uic_mqtt_dotdot_parse_unify_thermostat_write_attributes( - jsn, - new_state, - new_updated_state - ); - } catch (const nlohmann::json::parse_error& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyThermostat", "WriteAttributes"); - return; - } catch (const nlohmann::json::exception& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", e.what()); - return; - } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", ""); - return; - } - - for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_write_attributes_callback){ - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - new_state, - new_updated_state - ); - } - -} - -static void uic_mqtt_dotdot_on_unify_thermostat_force_read_attributes( - const char *topic, - const char *message, - const size_t message_length) -{ - uint8_t endpoint = 0; - std::string unid; - - if ((message_length == 0) || (uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.empty())) { - return; - } - - if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { - sl_log_debug(LOG_TAG, - "Error parsing UNID / Endpoint ID from topic %s. Ignoring", - topic); - return; - } - - try { - uic_mqtt_dotdot_unify_thermostat_updated_state_t force_update = {0}; - bool trigger_handler = false; - - nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - std::vector attributes = jsn["value"].get>(); - - // Assume all attributes to be read on empty array received - if (attributes.size() == 0) { - force_update.thermostat_mode = true; - force_update.supported_thermostat_mode = true; - force_update.operating_state = true; - trigger_handler = true; - } else { - std::unordered_map supported_attrs = { - {"ThermostatMode", &force_update.thermostat_mode }, - {"SupportedThermostatMode", &force_update.supported_thermostat_mode }, - {"OperatingState", &force_update.operating_state }, - }; - - for (auto& attribute : attributes) { - auto found_attr = supported_attrs.find(attribute); - if (found_attr != supported_attrs.end()) { - *(found_attr->second) = true; - trigger_handler = true; - } - } - } - - if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback) { - callback( - static_cast(unid.c_str()), - endpoint, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - force_update - ); - } - } - } catch (...) { - sl_log_debug(LOG_TAG, "UnifyThermostat/Commands/ForceReadAttributes: Unable to parse JSON payload"); - return; - } -} - -sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( - const char *base_topic, - uint8_t value, - uic_mqtt_dotdot_attribute_publish_type_t publish_type -) -{ - nlohmann::json jsn; - - // This is a single value - - #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_thermostat_thermostat_mode_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_THERMOSTAT_THERMOSTAT_MODE. Using number instead."); - jsn["value"] = static_cast(value); - #endif - - - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); - } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/ThermostatMode", e.what()); - return SL_STATUS_OK; + nlohmann::json bitmap_values = UserCredentialSupportedUserTypes.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportedUserTypes", e.what()); + return SL_STATUS_OK; } + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); - std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/ThermostatMode"; + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportedUserTypes"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -95673,14 +95427,14 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_unretain( +sl_status_t uic_mqtt_dotdot_user_credential_supported_user_types_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyThermostat/Attributes/ThermostatMode"; + + "/UserCredential/Attributes/SupportedUserTypes"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -95696,9 +95450,9 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( +sl_status_t uic_mqtt_dotdot_user_credential_support_credential_checksum_publish( const char *base_topic, - uint16_t value, + bool value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -95706,8 +95460,11 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( // This is a single value - nlohmann::json bitmap_values = UnifyThermostatSupportedThermostatMode.get_bitmap_values_as_json_tree((uint32_t)value); - jsn["value"] = bitmap_values; + if (true == uic_dotdot_has_attribute_value_a_name(64776,4,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64776,4,value); + }else{ + jsn["value"] = value; + } std::string payload_str; @@ -95715,14 +95472,12 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/SupportedThermostatMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportCredentialChecksum", e.what()); return SL_STATUS_OK; } - boost::replace_all(payload_str, "\"true\"", "true"); - boost::replace_all(payload_str, "\"false\"", "false"); - std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/SupportedThermostatMode"; + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportCredentialChecksum"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -95742,14 +95497,14 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_unretain( +sl_status_t uic_mqtt_dotdot_user_credential_support_credential_checksum_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyThermostat/Attributes/SupportedThermostatMode"; + + "/UserCredential/Attributes/SupportCredentialChecksum"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -95765,9 +95520,9 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_publish( +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_publish( const char *base_topic, - uint8_t value, + bool value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -95775,14 +95530,11 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_publish( // This is a single value - #ifdef UNIFY_THERMOSTAT_OPERATING_STATE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_thermostat_operating_state_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_THERMOSTAT_OPERATING_STATE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + if (true == uic_dotdot_has_attribute_value_a_name(64776,5,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64776,5,value); + }else{ + jsn["value"] = value; + } std::string payload_str; @@ -95790,12 +95542,12 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/OperatingState", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportAdminPinCode", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/OperatingState"; + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportAdminPinCode"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -95815,14 +95567,14 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_unretain( +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyThermostat/Attributes/OperatingState"; + + "/UserCredential/Attributes/SupportAdminPinCode"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -95838,152 +95590,483 @@ sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_unretain( } // clang-format off +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_publish( + const char *base_topic, + bool value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) +{ + nlohmann::json jsn; + + // This is a single value -sl_status_t uic_mqtt_dotdot_unify_thermostat_init() + if (true == uic_dotdot_has_attribute_value_a_name(64776,6,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64776,6,value); + }else{ + jsn["value"] = value; + } + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/SupportAdminPinCodeDeactivation", e.what()); + return SL_STATUS_OK; + } + + + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/SupportAdminPinCodeDeactivation"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; +} + +sl_status_t uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) +{ + // clang-format on + std::string topic + = std::string(base_topic) + + "/UserCredential/Attributes/SupportAdminPinCodeDeactivation"; + + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; +} +// clang-format off + +sl_status_t uic_mqtt_dotdot_user_credential_admin_pin_code_publish( + const char *base_topic, + const char* value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) +{ + nlohmann::json jsn; + + // This is a single value + + jsn["value"] = std::string(value); + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential/Attributes/AdminPinCode", e.what()); + return SL_STATUS_OK; + } + + + std::string topic = std::string(base_topic) + "/UserCredential/Attributes/AdminPinCode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; +} + +sl_status_t uic_mqtt_dotdot_user_credential_admin_pin_code_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) +{ + // clang-format on + std::string topic + = std::string(base_topic) + + "/UserCredential/Attributes/AdminPinCode"; + + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; +} +// clang-format off + + +sl_status_t uic_mqtt_dotdot_user_credential_init() { std::string base_topic = "ucl/by-unid/+/+/"; std::string subscription_topic; - if(!uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.empty()) { - subscription_topic = base_topic + "UnifyThermostat/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes); + if(!uic_mqtt_dotdot_user_credential_write_attributes_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_WriteAttributes); } - if(!uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "UnifyThermostat/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_thermostat_force_read_attributes); + if(!uic_mqtt_dotdot_user_credential_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_force_read_attributes); + } + if (!uic_mqtt_dotdot_user_credential_add_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/AddUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_add_user); + } + if (!uic_mqtt_dotdot_user_credential_generated_add_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/AddUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_add_user); + } + if (!uic_mqtt_dotdot_user_credential_modify_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/ModifyUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_modify_user); + } + if (!uic_mqtt_dotdot_user_credential_generated_modify_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/ModifyUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_modify_user); + } + if (!uic_mqtt_dotdot_user_credential_delete_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_user); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_user); + } + if (!uic_mqtt_dotdot_user_credential_add_credential_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/AddCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_add_credential); + } + if (!uic_mqtt_dotdot_user_credential_generated_add_credential_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/AddCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_add_credential); + } + if (!uic_mqtt_dotdot_user_credential_modify_credential_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/ModifyCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_modify_credential); + } + if (!uic_mqtt_dotdot_user_credential_generated_modify_credential_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/ModifyCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_modify_credential); + } + if (!uic_mqtt_dotdot_user_credential_delete_credential_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_credential); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_credential_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_credential); + } + if (!uic_mqtt_dotdot_user_credential_delete_all_users_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteAllUsers"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_all_users); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_all_users_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteAllUsers"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_all_users); + } + if (!uic_mqtt_dotdot_user_credential_delete_all_credentials_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteAllCredentials"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_all_credentials); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteAllCredentials"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials); + } + if (!uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteAllCredentialsByType"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_all_credentials_by_type); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_by_type_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteAllCredentialsByType"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials_by_type); + } + if (!uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteAllCredentialsForUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteAllCredentialsForUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials_for_user); + } + if (!uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeleteAllCredentialsForUserByType"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user_by_type); + } + if (!uic_mqtt_dotdot_user_credential_generated_delete_all_credentials_for_user_by_type_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_delete_all_credentials_for_user_by_type); + } + if (!uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/CredentialLearnStartAdd"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_credential_learn_start_add); + } + if (!uic_mqtt_dotdot_user_credential_generated_credential_learn_start_add_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/CredentialLearnStartAdd"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_credential_learn_start_add); + } + if (!uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/CredentialLearnStartModify"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_credential_learn_start_modify); + } + if (!uic_mqtt_dotdot_user_credential_generated_credential_learn_start_modify_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/CredentialLearnStartModify"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_credential_learn_start_modify); + } + if (!uic_mqtt_dotdot_user_credential_credential_learn_stop_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/CredentialLearnStop"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_credential_learn_stop); + } + if (!uic_mqtt_dotdot_user_credential_generated_credential_learn_stop_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/CredentialLearnStop"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_credential_learn_stop); + } + if (!uic_mqtt_dotdot_user_credential_credential_association_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/CredentialAssociation"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_credential_association); + } + if (!uic_mqtt_dotdot_user_credential_generated_credential_association_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/CredentialAssociation"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_credential_association); + } + if (!uic_mqtt_dotdot_user_credential_get_user_checksum_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/GetUserChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_get_user_checksum); + } + if (!uic_mqtt_dotdot_user_credential_generated_get_user_checksum_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/GetUserChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_get_user_checksum); + } + if (!uic_mqtt_dotdot_user_credential_get_credential_checksum_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/GetCredentialChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_get_credential_checksum); + } + if (!uic_mqtt_dotdot_user_credential_generated_get_credential_checksum_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/GetCredentialChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_get_credential_checksum); + } + if (!uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/GetAllUsersChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_get_all_users_checksum); + } + if (!uic_mqtt_dotdot_user_credential_generated_get_all_users_checksum_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/GetAllUsersChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_get_all_users_checksum); + } + if (!uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/SetAdminPINCode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_set_admin_pin_code); + } + if (!uic_mqtt_dotdot_user_credential_generated_set_admin_pin_code_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/SetAdminPINCode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_set_admin_pin_code); + } + if (!uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback.empty()) { + subscription_topic = base_topic + "UserCredential/Commands/DeactivateAdminPINCode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_user_credential_deactivate_admin_pin_code); + } + if (!uic_mqtt_dotdot_user_credential_generated_deactivate_admin_pin_code_callback.empty()) { + subscription_topic = base_topic + "UserCredential/GeneratedCommands/DeactivateAdminPINCode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_user_credential_deactivate_admin_pin_code); } // Init the attributes for that cluster - uic_mqtt_dotdot_unify_thermostat_attributes_init(); + uic_mqtt_dotdot_user_credential_attributes_init(); - uic_mqtt_dotdot_by_group_unify_thermostat_init(); + uic_mqtt_dotdot_by_group_user_credential_init(); return SL_STATUS_OK; } // Callbacks pointers -static std::set uic_mqtt_dotdot_unify_humidity_control_mode_set_callback; -static std::set uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback; -static std::set uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback; -static std::set uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback; -static std::set uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback; -static std::set uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback; +static std::set uic_mqtt_dotdot_aox_locator_iq_report_callback; +static std::set uic_mqtt_dotdot_aox_locator_generated_iq_report_callback; +static std::set uic_mqtt_dotdot_aox_locator_angle_report_callback; +static std::set uic_mqtt_dotdot_aox_locator_generated_angle_report_callback; +static std::set uic_mqtt_dotdot_aox_locator_angle_correction_callback; +static std::set uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback; +static std::set uic_mqtt_dotdot_aox_locator_write_attributes_callback; +static std::set uic_mqtt_dotdot_aox_locator_force_read_attributes_callback; // Callbacks setters -void uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_iq_report_callback_set(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.insert(callback); + uic_mqtt_dotdot_aox_locator_iq_report_callback.insert(callback); } } -void uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_iq_report_callback_unset(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) { - uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.erase(callback); + uic_mqtt_dotdot_aox_locator_iq_report_callback.erase(callback); } -void uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_clear() +void uic_mqtt_dotdot_aox_locator_iq_report_callback_clear() { - uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.clear(); + uic_mqtt_dotdot_aox_locator_iq_report_callback.clear(); } -std::set& get_uic_mqtt_dotdot_unify_humidity_control_mode_set_callback() +std::set& get_uic_mqtt_dotdot_aox_locator_iq_report_callback() { - return uic_mqtt_dotdot_unify_humidity_control_mode_set_callback; + return uic_mqtt_dotdot_aox_locator_iq_report_callback; } -void uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_generated_iq_report_callback_set(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.insert(callback); + uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.insert(callback); } } -void uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_generated_iq_report_callback_unset(const uic_mqtt_dotdot_aox_locator_iq_report_callback_t callback) { - uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.erase(callback); + uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.erase(callback); } -void uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback_clear() +void uic_mqtt_dotdot_aox_locator_generated_iq_report_callback_clear() { - uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.clear(); + uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.clear(); } -void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_angle_report_callback_set(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.insert(callback); + uic_mqtt_dotdot_aox_locator_angle_report_callback.insert(callback); } } -void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_angle_report_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) { - uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.erase(callback); + uic_mqtt_dotdot_aox_locator_angle_report_callback.erase(callback); } -void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_clear() +void uic_mqtt_dotdot_aox_locator_angle_report_callback_clear() { - uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.clear(); + uic_mqtt_dotdot_aox_locator_angle_report_callback.clear(); } -std::set& get_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback() +std::set& get_uic_mqtt_dotdot_aox_locator_angle_report_callback() { - return uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback; + return uic_mqtt_dotdot_aox_locator_angle_report_callback; } -void uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_generated_angle_report_callback_set(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.insert(callback); + uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.insert(callback); } } -void uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +void uic_mqtt_dotdot_aox_locator_generated_angle_report_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_report_callback_t callback) { - uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.erase(callback); + uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.erase(callback); } -void uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback_clear() +void uic_mqtt_dotdot_aox_locator_generated_angle_report_callback_clear() { - uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.clear(); + uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.clear(); } - -void uic_mqtt_dotdot_set_unify_humidity_control_write_attributes_callback( - const uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback_t callback) +void uic_mqtt_dotdot_aox_locator_angle_correction_callback_set(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.insert(callback); + uic_mqtt_dotdot_aox_locator_angle_correction_callback.insert(callback); } } -void uic_mqtt_dotdot_unset_unify_humidity_control_write_attributes_callback( - const uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback_t callback) +void uic_mqtt_dotdot_aox_locator_angle_correction_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) { - uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.erase(callback); + uic_mqtt_dotdot_aox_locator_angle_correction_callback.erase(callback); } -void uic_mqtt_dotdot_clear_unify_humidity_control_write_attributes_callbacks() +void uic_mqtt_dotdot_aox_locator_angle_correction_callback_clear() { - uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.clear(); + uic_mqtt_dotdot_aox_locator_angle_correction_callback.clear(); } -std::set& get_uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback() +std::set& get_uic_mqtt_dotdot_aox_locator_angle_correction_callback() { - return uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback; + return uic_mqtt_dotdot_aox_locator_angle_correction_callback; } -void uic_mqtt_dotdot_set_unify_humidity_control_force_read_attributes_callback( - const uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback_t callback) +void uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback_set(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) { if (callback != nullptr) { - uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.insert(callback); + uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.insert(callback); } } -void uic_mqtt_dotdot_unset_unify_humidity_control_force_read_attributes_callback( - const uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback_t callback) +void uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback_unset(const uic_mqtt_dotdot_aox_locator_angle_correction_callback_t callback) { - uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.erase(callback); + uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.erase(callback); } -void uic_mqtt_dotdot_clear_unify_humidity_control_force_read_attributes_callbacks() +void uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback_clear() { - uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.clear(); + uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.clear(); +} + +void uic_mqtt_dotdot_set_aox_locator_write_attributes_callback( + const uic_mqtt_dotdot_aox_locator_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_aox_locator_write_attributes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unset_aox_locator_write_attributes_callback( + const uic_mqtt_dotdot_aox_locator_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_aox_locator_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_aox_locator_write_attributes_callbacks() +{ + uic_mqtt_dotdot_aox_locator_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_aox_locator_write_attributes_callback() +{ + return uic_mqtt_dotdot_aox_locator_write_attributes_callback; +} + +void uic_mqtt_dotdot_set_aox_locator_force_read_attributes_callback( + const uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unset_aox_locator_force_read_attributes_callback( + const uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_aox_locator_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.clear(); } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/Commands/ModeSet -void uic_mqtt_dotdot_on_unify_humidity_control_mode_set( +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/IQReport +void uic_mqtt_dotdot_on_aox_locator_iq_report( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_iq_report_callback.empty())) { return; } @@ -95996,7 +96079,11 @@ void uic_mqtt_dotdot_on_unify_humidity_control_mode_set( return; } - ModeType mode = {}; + std::string tag_unid; + uint8_t channel = {}; + int8_t rssi = {}; + std::vector samples; + int32_t sequence = {}; nlohmann::json jsn; @@ -96004,45 +96091,62 @@ void uic_mqtt_dotdot_on_unify_humidity_control_mode_set( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_humidity_control_mode_set( + uic_mqtt_dotdot_parse_aox_locator_iq_report( jsn, - mode + tag_unid, + + channel, + + rssi, + + samples, + + sequence ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "ModeSet"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "IQReport"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_mode_set_callback){ + for (const auto& callback: uic_mqtt_dotdot_aox_locator_iq_report_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - mode + tag_unid.c_str(), + + channel, + + rssi, + + samples.size(), + samples.data(), + + sequence ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/GeneratedCommands/ModeSet -static void uic_mqtt_dotdot_on_generated_unify_humidity_control_mode_set( +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/GeneratedCommands/IQReport +static void uic_mqtt_dotdot_on_generated_aox_locator_iq_report( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.empty())) { return; } @@ -96055,7 +96159,11 @@ static void uic_mqtt_dotdot_on_generated_unify_humidity_control_mode_set( return; } - ModeType mode = {}; + std::string tag_unid; + uint8_t channel = {}; + int8_t rssi = {}; + std::vector samples; + int32_t sequence = {}; nlohmann::json jsn; @@ -96063,46 +96171,63 @@ static void uic_mqtt_dotdot_on_generated_unify_humidity_control_mode_set( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_humidity_control_mode_set( + uic_mqtt_dotdot_parse_aox_locator_iq_report( jsn, - mode + tag_unid, + + channel, + + rssi, + + samples, + + sequence ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "ModeSet"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "IQReport"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback){ + for (const auto& callback: uic_mqtt_dotdot_aox_locator_generated_iq_report_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - mode + tag_unid.c_str(), + + channel, + + rssi, + + samples.size(), + samples.data(), + + sequence ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/Commands/SetpointSet -void uic_mqtt_dotdot_on_unify_humidity_control_setpoint_set( +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/AngleReport +void uic_mqtt_dotdot_on_aox_locator_angle_report( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_angle_report_callback.empty())) { return; } @@ -96115,10 +96240,10 @@ void uic_mqtt_dotdot_on_unify_humidity_control_setpoint_set( return; } - SetpointType type = {}; - uint8_t precision = {}; - uint8_t scale = {}; - int32_t value = {}; + std::string tag_unid; + SphericalCoordinates direction = {}; + SphericalCoordinates deviation = {}; + int32_t sequence = {}; nlohmann::json jsn; @@ -96126,57 +96251,57 @@ void uic_mqtt_dotdot_on_unify_humidity_control_setpoint_set( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_humidity_control_setpoint_set( + uic_mqtt_dotdot_parse_aox_locator_angle_report( jsn, - type, + tag_unid, - precision, + direction, - scale, + deviation, - value + sequence ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "SetpointSet"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleReport"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback){ + for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_report_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - type, + tag_unid.c_str(), - precision, + direction, - scale, + deviation, - value + sequence ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/GeneratedCommands/SetpointSet -static void uic_mqtt_dotdot_on_generated_unify_humidity_control_setpoint_set( +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/GeneratedCommands/AngleReport +static void uic_mqtt_dotdot_on_generated_aox_locator_angle_report( const char *topic, const char *message, const size_t message_length) { - if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.empty())) { + if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.empty())) { return; } @@ -96189,10 +96314,10 @@ static void uic_mqtt_dotdot_on_generated_unify_humidity_control_setpoint_set( return; } - SetpointType type = {}; - uint8_t precision = {}; - uint8_t scale = {}; - int32_t value = {}; + std::string tag_unid; + SphericalCoordinates direction = {}; + SphericalCoordinates deviation = {}; + int32_t sequence = {}; nlohmann::json jsn; @@ -96200,62 +96325,58 @@ static void uic_mqtt_dotdot_on_generated_unify_humidity_control_setpoint_set( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_humidity_control_setpoint_set( + uic_mqtt_dotdot_parse_aox_locator_angle_report( jsn, - type, + tag_unid, - precision, + direction, - scale, + deviation, - value + sequence ); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "SetpointSet"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleReport"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback){ + for (const auto& callback: uic_mqtt_dotdot_aox_locator_generated_angle_report_callback){ callback( static_cast(unid.c_str()), endpoint, UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, - type, + tag_unid.c_str(), - precision, + direction, - scale, + deviation, - value + sequence ); } } -// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/Commands/WriteAttributes -void uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes( +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/AngleCorrection +void uic_mqtt_dotdot_on_aox_locator_angle_correction( const char *topic, const char *message, const size_t message_length) { - if (uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.empty()) { - return; - } - - if (message_length == 0) { + if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_angle_correction_callback.empty())) { return; } @@ -96268,33 +96389,198 @@ void uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes( return; } - uic_mqtt_dotdot_unify_humidity_control_state_t new_state = {}; - uic_mqtt_dotdot_unify_humidity_control_updated_state_t new_updated_state = {}; + std::string tag_unid; + SphericalCoordinates direction = {}; + SphericalCoordinates deviation = {}; + int32_t sequence = {}; nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_unify_humidity_control_write_attributes( + + uic_mqtt_dotdot_parse_aox_locator_angle_correction( jsn, - new_state, - new_updated_state - ); - } catch (const nlohmann::json::parse_error& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "WriteAttributes"); - return; - } catch (const nlohmann::json::exception& e) { - // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "WriteAttributes", e.what()); - return; + tag_unid, + + direction, + + deviation, + + sequence + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleCorrection"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", e.what()); + return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "WriteAttributes", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", ""); return; } - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback){ + + + for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_correction_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + tag_unid.c_str(), + + direction, + + deviation, + + sequence + + ); + } + +} + +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/GeneratedCommands/AngleCorrection +static void uic_mqtt_dotdot_on_generated_aox_locator_angle_correction( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.empty())) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string tag_unid; + SphericalCoordinates direction = {}; + SphericalCoordinates deviation = {}; + int32_t sequence = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_aox_locator_angle_correction( + jsn, + tag_unid, + + direction, + + deviation, + + sequence + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleCorrection"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", ""); + return; + } + + + + + for (const auto& callback: uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + tag_unid.c_str(), + + direction, + + deviation, + + sequence + + ); + } +} + + +// Callback function for incoming publications on ucl/by-unid/+/+/AoXLocator/Commands/WriteAttributes +void uic_mqtt_dotdot_on_aox_locator_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) +{ + if (uic_mqtt_dotdot_aox_locator_write_attributes_callback.empty()) { + return; + } + + if (message_length == 0) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_aox_locator_state_t new_state = {}; + uic_mqtt_dotdot_aox_locator_updated_state_t new_updated_state = {}; + + std::vector azimuth_mask; + + std::vector elevation_mask; + + std::vector allow_list; + + std::vector antenna_array; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_aox_locator_write_attributes( + jsn, + new_state, + new_updated_state, + azimuth_mask, + elevation_mask, + allow_list, + antenna_array + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "WriteAttributes", ""); + return; + } + + for (const auto& callback: uic_mqtt_dotdot_aox_locator_write_attributes_callback){ callback( static_cast(unid.c_str()), endpoint, @@ -96306,7 +96592,7 @@ void uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes( } -static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( +static void uic_mqtt_dotdot_on_aox_locator_force_read_attributes( const char *topic, const char *message, const size_t message_length) @@ -96314,7 +96600,7 @@ static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( uint8_t endpoint = 0; std::string unid; - if ((message_length == 0) || (uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.empty())) { + if ((message_length == 0) || (uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.empty())) { return; } @@ -96326,7 +96612,7 @@ static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( } try { - uic_mqtt_dotdot_unify_humidity_control_updated_state_t force_update = {0}; + uic_mqtt_dotdot_aox_locator_updated_state_t force_update = {0}; bool trigger_handler = false; nlohmann::json jsn = nlohmann::json::parse(std::string(message)); @@ -96335,46 +96621,44 @@ static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( // Assume all attributes to be read on empty array received if (attributes.size() == 0) { force_update.reporting_mode = true; - force_update.supported_reporting_mode = true; - force_update.current_state = true; - force_update.supported_set_points = true; - force_update.humidifier_setpoint_min = true; - force_update.humidifier_setpoint_max = true; - force_update.humidifier_setpoint = true; - force_update.humidifier_setpoint_scale = true; - force_update.humidifier_setpoint_precision = true; - force_update.dehumidifier_setpoint_min = true; - force_update.dehumidifier_setpoint_max = true; - force_update.dehumidifier_setpoint = true; - force_update.dehumidifier_setpoint_scale = true; - force_update.dehumidifier_setpoint_precision = true; - force_update.auto_setpoint_min = true; - force_update.auto_setpoint_max = true; - force_update.auto_setpoint = true; - force_update.auto_setpoint_scale = true; - force_update.auto_setpoint_precision = true; + force_update.position_and_orientation_valid = true; + force_update.position_and_orientation = true; + force_update.azimuth_mask = true; + force_update.elevation_mask = true; + force_update.allow_list = true; + force_update.aox_mode = true; + force_update.antenna_mode = true; + force_update.antenna_array = true; + force_update.period_samples = true; + force_update.angle_filtering = true; + force_update.angle_filtering_weight = true; + force_update.angle_correction_timeout = true; + force_update.angle_correction_delay = true; + force_update.cte_mode = true; + force_update.cte_sampling_interval = true; + force_update.cte_length = true; + force_update.slot_duration = true; trigger_handler = true; } else { std::unordered_map supported_attrs = { {"ReportingMode", &force_update.reporting_mode }, - {"SupportedReportingMode", &force_update.supported_reporting_mode }, - {"CurrentState", &force_update.current_state }, - {"SupportedSetPoints", &force_update.supported_set_points }, - {"HumidifierSetpointMin", &force_update.humidifier_setpoint_min }, - {"HumidifierSetpointMax", &force_update.humidifier_setpoint_max }, - {"HumidifierSetpoint", &force_update.humidifier_setpoint }, - {"HumidifierSetpointScale", &force_update.humidifier_setpoint_scale }, - {"HumidifierSetpointPrecision", &force_update.humidifier_setpoint_precision }, - {"DehumidifierSetpointMin", &force_update.dehumidifier_setpoint_min }, - {"DehumidifierSetpointMax", &force_update.dehumidifier_setpoint_max }, - {"DehumidifierSetpoint", &force_update.dehumidifier_setpoint }, - {"DehumidifierSetpointScale", &force_update.dehumidifier_setpoint_scale }, - {"DehumidifierSetpointPrecision", &force_update.dehumidifier_setpoint_precision }, - {"AutoSetpointMin", &force_update.auto_setpoint_min }, - {"AutoSetpointMax", &force_update.auto_setpoint_max }, - {"AutoSetpoint", &force_update.auto_setpoint }, - {"AutoSetpointScale", &force_update.auto_setpoint_scale }, - {"AutoSetpointPrecision", &force_update.auto_setpoint_precision }, + {"PositionAndOrientationValid", &force_update.position_and_orientation_valid }, + {"PositionAndOrientation", &force_update.position_and_orientation }, + {"AzimuthMask", &force_update.azimuth_mask }, + {"ElevationMask", &force_update.elevation_mask }, + {"AllowList", &force_update.allow_list }, + {"AoXMode", &force_update.aox_mode }, + {"AntennaMode", &force_update.antenna_mode }, + {"AntennaArray", &force_update.antenna_array }, + {"PeriodSamples", &force_update.period_samples }, + {"AngleFiltering", &force_update.angle_filtering }, + {"AngleFilteringWeight", &force_update.angle_filtering_weight }, + {"AngleCorrectionTimeout", &force_update.angle_correction_timeout }, + {"AngleCorrectionDelay", &force_update.angle_correction_delay }, + {"CTEMode", &force_update.cte_mode }, + {"CTESamplingInterval", &force_update.cte_sampling_interval }, + {"CTELength", &force_update.cte_length }, + {"SlotDuration", &force_update.slot_duration }, }; for (auto& attribute : attributes) { @@ -96387,7 +96671,7 @@ static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( } if (trigger_handler == true) { - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback) { + for (const auto& callback: uic_mqtt_dotdot_aox_locator_force_read_attributes_callback) { callback( static_cast(unid.c_str()), endpoint, @@ -96397,14 +96681,14 @@ static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( } } } catch (...) { - sl_log_debug(LOG_TAG, "UnifyHumidityControl/Commands/ForceReadAttributes: Unable to parse JSON payload"); + sl_log_debug(LOG_TAG, "AoXLocator/Commands/ForceReadAttributes: Unable to parse JSON payload"); return; } } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_reporting_mode_publish( const char *base_topic, - ModeType value, + uint8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -96412,13 +96696,13 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_publish( // This is a single value - #ifdef UNIFY_HUMIDITY_CONTROL_REPORTING_MODE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_humidity_control_reporting_mode_get_enum_value_name((uint32_t)value); - #elif defined(MODE_TYPE_ENUM_NAME_AVAILABLE) - jsn["value"] = mode_type_get_enum_value_name((uint32_t)value); + #ifdef AOX_LOCATOR_REPORTING_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = aox_locator_reporting_mode_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_REPORTING_MODE. Using number instead."); - jsn["value"] = static_cast(value); + sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_REPORTING_MODE. Using number instead."); + jsn["value"] = static_cast(value); #endif @@ -96427,12 +96711,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/ReportingMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/ReportingMode", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/ReportingMode"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/ReportingMode"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -96452,14 +96736,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_reporting_mode_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/ReportingMode"; + + "/AoXLocator/Attributes/ReportingMode"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -96475,9 +96759,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_valid_publish( const char *base_topic, - uint8_t value, + bool value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -96485,8 +96769,11 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_publ // This is a single value - nlohmann::json bitmap_values = UnifyHumidityControlSupportedReportingMode.get_bitmap_values_as_json_tree((uint32_t)value); - jsn["value"] = bitmap_values; + if (true == uic_dotdot_has_attribute_value_a_name(64784,2,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64784,2,value); + }else{ + jsn["value"] = value; + } std::string payload_str; @@ -96494,14 +96781,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_publ // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/SupportedReportingMode", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/PositionAndOrientationValid", e.what()); return SL_STATUS_OK; } - boost::replace_all(payload_str, "\"true\"", "true"); - boost::replace_all(payload_str, "\"false\"", "false"); - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/SupportedReportingMode"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/PositionAndOrientationValid"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -96521,14 +96806,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_publ return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_valid_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/SupportedReportingMode"; + + "/AoXLocator/Attributes/PositionAndOrientationValid"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -96544,9 +96829,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_unre } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_publish( const char *base_topic, - uint8_t value, + CoordinateAndOrientation value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -96554,14 +96839,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_publish( // This is a single value - #ifdef UNIFY_HUMIDITY_CONTROL_CURRENT_STATE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_humidity_control_current_state_get_enum_value_name((uint32_t)value); - #elif defined(ENUM8_ENUM_NAME_AVAILABLE) - jsn["value"] = enum8_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_CURRENT_STATE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + nlohmann::json json_object = nlohmann::json::object(); + json_object["CoordinateX"] = value.CoordinateX; + json_object["CoordinateY"] = value.CoordinateY; + json_object["CoordinateZ"] = value.CoordinateZ; + json_object["OrientationX"] = value.OrientationX; + json_object["OrientationY"] = value.OrientationY; + json_object["OrientationZ"] = value.OrientationZ; + jsn["value"]= json_object; std::string payload_str; @@ -96569,12 +96854,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/CurrentState", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/PositionAndOrientation", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/CurrentState"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/PositionAndOrientation"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -96594,14 +96879,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_position_and_orientation_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/CurrentState"; + + "/AoXLocator/Attributes/PositionAndOrientation"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -96617,18 +96902,27 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_set_points_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_azimuth_mask_publish( const char *base_topic, - uint8_t value, + size_t value_count, + const MinMaxPair* value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { nlohmann::json jsn; - // This is a single value + // This is a variable size array of the same known type. + // Create an array under the value {"value":[]} + jsn["value"] = nlohmann::json::array(); + + for (size_t i = 0; i(value); + #endif std::string payload_str; @@ -96848,12 +97152,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpoint", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AoXMode", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpoint"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AoXMode"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -96873,14 +97177,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_aox_mode_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/HumidifierSetpoint"; + + "/AoXLocator/Attributes/AoXMode"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -96896,9 +97200,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_antenna_mode_publish( const char *base_topic, - ScaleType value, + uint8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -96906,13 +97210,13 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_pub // This is a single value - #ifdef UNIFY_HUMIDITY_CONTROL_HUMIDIFIER_SETPOINT_SCALE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_humidity_control_humidifier_setpoint_scale_get_enum_value_name((uint32_t)value); - #elif defined(SCALE_TYPE_ENUM_NAME_AVAILABLE) - jsn["value"] = scale_type_get_enum_value_name((uint32_t)value); + #ifdef AOX_LOCATOR_ANTENNA_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = aox_locator_antenna_mode_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_HUMIDIFIER_SETPOINT_SCALE. Using number instead."); - jsn["value"] = static_cast(value); + sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_ANTENNA_MODE. Using number instead."); + jsn["value"] = static_cast(value); #endif @@ -96921,12 +97225,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_pub // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpointScale", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AntennaMode", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpointScale"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AntennaMode"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -96946,14 +97250,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_pub return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_antenna_mode_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/HumidifierSetpointScale"; + + "/AoXLocator/Attributes/AntennaMode"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -96969,34 +97273,36 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_unr } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_precision_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_antenna_array_publish( const char *base_topic, - uint8_t value, + size_t value_count, + const int8_t* value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { nlohmann::json jsn; - // This is a single value + // This is a variable size array of the same known type. + // Create an array under the value {"value":[]} + jsn["value"] = nlohmann::json::array(); - if (true == uic_dotdot_has_attribute_value_a_name(64928,9,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64928,9,value); - }else{ - jsn["value"] = value; + for (size_t i = 0; i(value); - #endif - - - std::string payload_str; - try { - // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters - payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); - } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpointScale", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleFilteringWeight", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpointScale"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleFilteringWeight"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97299,14 +97532,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_scale_p return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_scale_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_angle_filtering_weight_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/DehumidifierSetpointScale"; + + "/AoXLocator/Attributes/AngleFilteringWeight"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97322,9 +97555,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_scale_u } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precision_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_timeout_publish( const char *base_topic, - uint8_t value, + int8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -97332,8 +97565,8 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precisi // This is a single value - if (true == uic_dotdot_has_attribute_value_a_name(64928,14,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64928,14,value); + if (true == uic_dotdot_has_attribute_value_a_name(64784,14,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64784,14,value); }else{ jsn["value"] = value; } @@ -97344,12 +97577,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precisi // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpointPrecision", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleCorrectionTimeout", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpointPrecision"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleCorrectionTimeout"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97369,14 +97602,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precisi return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precision_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_timeout_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/DehumidifierSetpointPrecision"; + + "/AoXLocator/Attributes/AngleCorrectionTimeout"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97392,9 +97625,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precisi } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_delay_publish( const char *base_topic, - int32_t value, + int8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -97402,8 +97635,8 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_publish( // This is a single value - if (true == uic_dotdot_has_attribute_value_a_name(64928,15,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64928,15,value); + if (true == uic_dotdot_has_attribute_value_a_name(64784,15,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64784,15,value); }else{ jsn["value"] = value; } @@ -97414,12 +97647,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointMin", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/AngleCorrectionDelay", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointMin"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/AngleCorrectionDelay"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97439,14 +97672,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_angle_correction_delay_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/AutoSetpointMin"; + + "/AoXLocator/Attributes/AngleCorrectionDelay"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97462,9 +97695,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_cte_mode_publish( const char *base_topic, - int32_t value, + uint8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -97472,11 +97705,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_publish( // This is a single value - if (true == uic_dotdot_has_attribute_value_a_name(64928,16,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64928,16,value); - }else{ - jsn["value"] = value; - } + #ifdef AOX_LOCATOR_CTE_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = aox_locator_cte_mode_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for AOX_LOCATOR_CTE_MODE. Using number instead."); + jsn["value"] = static_cast(value); + #endif std::string payload_str; @@ -97484,12 +97720,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointMax", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/CTEMode", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointMax"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/CTEMode"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97509,14 +97745,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_cte_mode_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/AutoSetpointMax"; + + "/AoXLocator/Attributes/CTEMode"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97532,9 +97768,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_cte_sampling_interval_publish( const char *base_topic, - int32_t value, + int8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -97542,8 +97778,8 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_publish( // This is a single value - if (true == uic_dotdot_has_attribute_value_a_name(64928,17,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64928,17,value); + if (true == uic_dotdot_has_attribute_value_a_name(64784,17,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64784,17,value); }else{ jsn["value"] = value; } @@ -97554,12 +97790,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpoint", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/CTESamplingInterval", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpoint"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/CTESamplingInterval"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97579,14 +97815,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_cte_sampling_interval_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/AutoSetpoint"; + + "/AoXLocator/Attributes/CTESamplingInterval"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97602,9 +97838,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_cte_length_publish( const char *base_topic, - ScaleType value, + int8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -97612,14 +97848,11 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_publish( // This is a single value - #ifdef UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE_ENUM_NAME_AVAILABLE - jsn["value"] = unify_humidity_control_auto_setpoint_scale_get_enum_value_name((uint32_t)value); - #elif defined(SCALE_TYPE_ENUM_NAME_AVAILABLE) - jsn["value"] = scale_type_get_enum_value_name((uint32_t)value); - #else - sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE. Using number instead."); - jsn["value"] = static_cast(value); - #endif + if (true == uic_dotdot_has_attribute_value_a_name(64784,18,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64784,18,value); + }else{ + jsn["value"] = value; + } std::string payload_str; @@ -97627,12 +97860,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_publish( // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointScale", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/CTELength", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointScale"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/CTELength"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97652,14 +97885,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_publish( return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_cte_length_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/AutoSetpointScale"; + + "/AoXLocator/Attributes/CTELength"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97675,9 +97908,9 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_unretain( } // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_publish( +sl_status_t uic_mqtt_dotdot_aox_locator_slot_duration_publish( const char *base_topic, - uint8_t value, + int8_t value, uic_mqtt_dotdot_attribute_publish_type_t publish_type ) { @@ -97685,8 +97918,8 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_publi // This is a single value - if (true == uic_dotdot_has_attribute_value_a_name(64928,19,value)) { - jsn["value"] = uic_dotdot_get_attribute_value_name(64928,19,value); + if (true == uic_dotdot_has_attribute_value_a_name(64784,19,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64784,19,value); }else{ jsn["value"] = value; } @@ -97697,12 +97930,12 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_publi // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); } catch (const nlohmann::json::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointPrecision", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator/Attributes/SlotDuration", e.what()); return SL_STATUS_OK; } - std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointPrecision"; + std::string topic = std::string(base_topic) + "/AoXLocator/Attributes/SlotDuration"; if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) { std::string topic_desired = topic + "/Desired"; @@ -97722,14 +97955,14 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_publi return SL_STATUS_OK; } -sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_unretain( +sl_status_t uic_mqtt_dotdot_aox_locator_slot_duration_unretain( const char *base_topic, uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on std::string topic = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/AutoSetpointPrecision"; + + "/AoXLocator/Attributes/SlotDuration"; if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { @@ -97746,5936 +97979,4527 @@ sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_unret // clang-format off -sl_status_t uic_mqtt_dotdot_unify_humidity_control_init() +sl_status_t uic_mqtt_dotdot_aox_locator_init() { std::string base_topic = "ucl/by-unid/+/+/"; std::string subscription_topic; - if(!uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.empty()) { - subscription_topic = base_topic + "UnifyHumidityControl/Commands/WriteAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes); + if(!uic_mqtt_dotdot_aox_locator_write_attributes_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_WriteAttributes); } - if(!uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.empty()) { - subscription_topic = base_topic + "UnifyHumidityControl/Commands/ForceReadAttributes"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes); + if(!uic_mqtt_dotdot_aox_locator_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_force_read_attributes); } - if (!uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.empty()) { - subscription_topic = base_topic + "UnifyHumidityControl/Commands/ModeSet"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_mode_set); + if (!uic_mqtt_dotdot_aox_locator_iq_report_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/Commands/IQReport"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_iq_report); } - if (!uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.empty()) { - subscription_topic = base_topic + "UnifyHumidityControl/GeneratedCommands/ModeSet"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_humidity_control_mode_set); + if (!uic_mqtt_dotdot_aox_locator_generated_iq_report_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/GeneratedCommands/IQReport"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_aox_locator_iq_report); } - if (!uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.empty()) { - subscription_topic = base_topic + "UnifyHumidityControl/Commands/SetpointSet"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_setpoint_set); + if (!uic_mqtt_dotdot_aox_locator_angle_report_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/Commands/AngleReport"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_angle_report); } - if (!uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.empty()) { - subscription_topic = base_topic + "UnifyHumidityControl/GeneratedCommands/SetpointSet"; - uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_humidity_control_setpoint_set); + if (!uic_mqtt_dotdot_aox_locator_generated_angle_report_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/GeneratedCommands/AngleReport"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_aox_locator_angle_report); + } + if (!uic_mqtt_dotdot_aox_locator_angle_correction_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/Commands/AngleCorrection"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_locator_angle_correction); + } + if (!uic_mqtt_dotdot_aox_locator_generated_angle_correction_callback.empty()) { + subscription_topic = base_topic + "AoXLocator/GeneratedCommands/AngleCorrection"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_aox_locator_angle_correction); } // Init the attributes for that cluster - uic_mqtt_dotdot_unify_humidity_control_attributes_init(); + uic_mqtt_dotdot_aox_locator_attributes_init(); - uic_mqtt_dotdot_by_group_unify_humidity_control_init(); + uic_mqtt_dotdot_by_group_aox_locator_init(); return SL_STATUS_OK; } +// Callbacks pointers +static std::set uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback; +static std::set uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback; -sl_status_t uic_mqtt_dotdot_init() { - - sl_status_t status_flag = SL_STATUS_OK; +// Callbacks setters - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_basic_init(); +void uic_mqtt_dotdot_set_aox_position_estimation_write_attributes_callback( + const uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.insert(callback); } +} +void uic_mqtt_dotdot_unset_aox_position_estimation_write_attributes_callback( + const uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_aox_position_estimation_write_attributes_callbacks() +{ + uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback() +{ + return uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback; +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_power_configuration_init(); +void uic_mqtt_dotdot_set_aox_position_estimation_force_read_attributes_callback( + const uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.insert(callback); } +} +void uic_mqtt_dotdot_unset_aox_position_estimation_force_read_attributes_callback( + const uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_aox_position_estimation_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.clear(); +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_device_temperature_configuration_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_identify_init(); +// Callback function for incoming publications on ucl/by-unid/+/+/AoXPositionEstimation/Commands/WriteAttributes +void uic_mqtt_dotdot_on_aox_position_estimation_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) +{ + if (uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.empty()) { + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_groups_init(); + if (message_length == 0) { + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_scenes_init(); + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_on_off_init(); - } + uic_mqtt_dotdot_aox_position_estimation_state_t new_state = {}; + uic_mqtt_dotdot_aox_position_estimation_updated_state_t new_updated_state = {}; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_level_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_alarms_init(); - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_time_init(); + uic_mqtt_dotdot_parse_aox_position_estimation_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXPositionEstimation", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXPositionEstimation", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXPositionEstimation", "WriteAttributes", ""); + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_poll_control_init(); + for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_shade_configuration_init(); - } +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_door_lock_init(); - } +static void uic_mqtt_dotdot_on_aox_position_estimation_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) +{ + uint8_t endpoint = 0; + std::string unid; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_window_covering_init(); + if ((message_length == 0) || (uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.empty())) { + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_barrier_control_init(); + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_pump_configuration_and_control_init(); - } + try { + uic_mqtt_dotdot_aox_position_estimation_updated_state_t force_update = {0}; + bool trigger_handler = false; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_thermostat_init(); - } + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_fan_control_init(); - } + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.position = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"Position", &force_update.position }, + }; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_dehumidification_control_init(); - } + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } + } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_thermostat_user_interface_configuration_init(); + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } + } + } catch (...) { + sl_log_debug(LOG_TAG, "AoXPositionEstimation/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; } +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_color_control_init(); - } +sl_status_t uic_mqtt_dotdot_aox_position_estimation_position_publish( + const char *base_topic, + EstimatedPosition value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) +{ + nlohmann::json jsn; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_ballast_configuration_init(); - } + // This is a single value - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_illuminance_measurement_init(); - } + nlohmann::json json_object = nlohmann::json::object(); + json_object["ApplicationId"] = value.ApplicationId; + json_object["X"] = value.X; + json_object["Y"] = value.Y; + json_object["Z"] = value.Z; + json_object["DeviationX"] = value.DeviationX; + json_object["DeviationY"] = value.DeviationY; + json_object["DeviationZ"] = value.DeviationZ; + json_object["Sequence"] = value.Sequence; + jsn["value"]= json_object; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_illuminance_level_sensing_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_temperature_measurement_init(); + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXPositionEstimation/Attributes/Position", e.what()); + return SL_STATUS_OK; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_pressure_measurement_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_flow_measurement_init(); + std::string topic = std::string(base_topic) + "/AoXPositionEstimation/Attributes/Position"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } - - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_relativity_humidity_init(); + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } + return SL_STATUS_OK; +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_occupancy_sensing_init(); - } +sl_status_t uic_mqtt_dotdot_aox_position_estimation_position_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) +{ + // clang-format on + std::string topic + = std::string(base_topic) + + "/AoXPositionEstimation/Attributes/Position"; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_soil_moisture_init(); + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } - - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_ph_measurement_init(); + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); } + return SL_STATUS_OK; +} +// clang-format off - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_electrical_conductivity_measurement_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_wind_speed_measurement_init(); - } +sl_status_t uic_mqtt_dotdot_aox_position_estimation_init() +{ + std::string base_topic = "ucl/by-unid/+/+/"; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_carbon_monoxide_init(); + std::string subscription_topic; + if(!uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback.empty()) { + subscription_topic = base_topic + "AoXPositionEstimation/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_position_estimation_WriteAttributes); } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_carbon_dioxide_init(); + if(!uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "AoXPositionEstimation/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_aox_position_estimation_force_read_attributes); } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_pm25_init(); - } + // Init the attributes for that cluster + uic_mqtt_dotdot_aox_position_estimation_attributes_init(); - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_ias_zone_init(); - } + uic_mqtt_dotdot_by_group_aox_position_estimation_init(); - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_iaswd_init(); - } + return SL_STATUS_OK; +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_metering_init(); - } +// Callbacks pointers +static std::set uic_mqtt_dotdot_protocol_controller_network_management_write_callback; +static std::set uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback; +static std::set uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback; +static std::set uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback; - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_electrical_measurement_init(); +// Callbacks setters +void uic_mqtt_dotdot_protocol_controller_network_management_write_callback_set(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_protocol_controller_network_management_write_callback.insert(callback); } +} +void uic_mqtt_dotdot_protocol_controller_network_management_write_callback_unset(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) +{ + uic_mqtt_dotdot_protocol_controller_network_management_write_callback.erase(callback); +} +void uic_mqtt_dotdot_protocol_controller_network_management_write_callback_clear() +{ + uic_mqtt_dotdot_protocol_controller_network_management_write_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_protocol_controller_network_management_write_callback() +{ + return uic_mqtt_dotdot_protocol_controller_network_management_write_callback; +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_diagnostics_init(); +void uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback_set(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.insert(callback); } +} +void uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback_unset(const uic_mqtt_dotdot_protocol_controller_network_management_write_callback_t callback) +{ + uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.erase(callback); +} +void uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback_clear() +{ + uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.clear(); +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_protocol_controller_rf_telemetry_init(); +void uic_mqtt_dotdot_set_protocol_controller_network_management_write_attributes_callback( + const uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.insert(callback); } +} +void uic_mqtt_dotdot_unset_protocol_controller_network_management_write_attributes_callback( + const uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_protocol_controller_network_management_write_attributes_callbacks() +{ + uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback() +{ + return uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback; +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_state_init(); +void uic_mqtt_dotdot_set_protocol_controller_network_management_force_read_attributes_callback( + const uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.insert(callback); } +} +void uic_mqtt_dotdot_unset_protocol_controller_network_management_force_read_attributes_callback( + const uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_protocol_controller_network_management_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.clear(); +} - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_binding_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_system_metrics_init(); +// Callback function for incoming publications on ucl/by-unid/+/+/ProtocolController-NetworkManagement/Commands/Write +void uic_mqtt_dotdot_on_protocol_controller_network_management_write( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_protocol_controller_network_management_write_callback.empty())) { + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_application_monitoring_init(); + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic_no_endpoint(topic,unid)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID from topic %s. Ignoring", + topic); + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_name_and_location_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_configuration_parameters_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_aox_locator_init(); - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_aox_position_estimation_init(); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "ProtocolController-NetworkManagement", "Write"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", ""); + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_protocol_controller_network_management_init(); - } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_descriptor_init(); + + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_unify_fan_control_init(); +} + +// Callback function for incoming publications on ucl/by-unid/+/+/ProtocolController-NetworkManagement/GeneratedCommands/Write +static void uic_mqtt_dotdot_on_generated_protocol_controller_network_management_write( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.empty())) { + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_unify_thermostat_init(); + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic_no_endpoint(topic,unid)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID from topic %s. Ignoring", + topic); + return; } - if (status_flag == SL_STATUS_OK) { - status_flag = uic_mqtt_dotdot_unify_humidity_control_init(); + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "ProtocolController-NetworkManagement", "Write"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "Write", ""); + return; } - return status_flag; + + + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); + } } -// Publish all supported dotdot cluster commands per each endpoints. -void uic_mqtt_dotdot_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uic_mqtt_dotdot_basic_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_power_configuration_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_device_temperature_configuration_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_identify_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_groups_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_scenes_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_on_off_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_level_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_alarms_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_time_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_poll_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_shade_configuration_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_door_lock_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_window_covering_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_barrier_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_thermostat_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_fan_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_dehumidification_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_color_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_ballast_configuration_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_illuminance_level_sensing_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_temperature_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_pressure_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_flow_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_relativity_humidity_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_soil_moisture_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_ph_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_electrical_conductivity_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_wind_speed_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_carbon_monoxide_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_carbon_dioxide_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_pm25_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_ias_zone_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_iaswd_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_metering_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_electrical_measurement_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_diagnostics_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_supported_commands(unid, 0); - uic_mqtt_dotdot_state_publish_supported_commands(unid, 0); - uic_mqtt_dotdot_binding_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_system_metrics_publish_supported_commands(unid, 0); - uic_mqtt_dotdot_application_monitoring_publish_supported_commands(unid, 0); - uic_mqtt_dotdot_name_and_location_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_configuration_parameters_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_aox_locator_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_commands(unid, 0); - uic_mqtt_dotdot_descriptor_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_unify_fan_control_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_unify_thermostat_publish_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_unify_humidity_control_publish_supported_commands(unid, endpoint_id); -} - -void uic_mqtt_dotdot_publish_empty_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uic_mqtt_dotdot_basic_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_power_configuration_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_device_temperature_configuration_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_identify_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_groups_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_scenes_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_on_off_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_level_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_alarms_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_time_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_poll_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_shade_configuration_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_door_lock_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_window_covering_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_barrier_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_pump_configuration_and_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_thermostat_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_fan_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_dehumidification_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_color_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_ballast_configuration_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_illuminance_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_illuminance_level_sensing_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_temperature_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_pressure_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_flow_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_relativity_humidity_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_occupancy_sensing_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_soil_moisture_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_ph_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_electrical_conductivity_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_wind_speed_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_carbon_monoxide_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_carbon_dioxide_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_pm25_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_ias_zone_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_iaswd_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_metering_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_electrical_measurement_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_diagnostics_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_empty_supported_commands(unid); - uic_mqtt_dotdot_state_publish_empty_supported_commands(unid); - uic_mqtt_dotdot_binding_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_system_metrics_publish_empty_supported_commands(unid); - uic_mqtt_dotdot_application_monitoring_publish_empty_supported_commands(unid); - uic_mqtt_dotdot_name_and_location_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_configuration_parameters_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_aox_locator_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_aox_position_estimation_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_protocol_controller_network_management_publish_empty_supported_commands(unid); - uic_mqtt_dotdot_descriptor_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_unify_fan_control_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands(unid, endpoint_id); - uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands(unid, endpoint_id); -} -// Publishing Cluster Revision for Basic Cluster -void uic_mqtt_dotdot_basic_publish_cluster_revision(const char* base_topic, uint16_t value) +// Callback function for incoming publications on ucl/by-unid/+/+/ProtocolController-NetworkManagement/Commands/WriteAttributes +void uic_mqtt_dotdot_on_protocol_controller_network_management_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) { - std::string cluster_topic = std::string(base_topic) + "/Basic/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} + if (uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.empty()) { + return; + } -// Unretain Cluster Revision for Basic Cluster -void uic_mqtt_dotdot_basic_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Basic/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + if (message_length == 0) { + return; + } -static inline bool uic_mqtt_dotdot_basic_reset_to_factory_defaults_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_basic_reset_to_factory_defaults_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic_no_endpoint(topic,unid)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID from topic %s. Ignoring", + topic); + return; } - return false; -} + uic_mqtt_dotdot_protocol_controller_network_management_state_t new_state = {}; + uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t new_updated_state = {}; -static inline bool uic_mqtt_dotdot_basic_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_basic_write_attributes_callback) { - uic_mqtt_dotdot_basic_state_t basic_new_state = {}; - uic_mqtt_dotdot_basic_updated_state_t basic_new_updated_state = {}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - basic_new_state, - basic_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_protocol_controller_network_management_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "ProtocolController-NetworkManagement", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController-NetworkManagement", "WriteAttributes", ""); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_basic_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_basic_force_read_attributes_callback) { - uic_mqtt_dotdot_basic_updated_state_t basic_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - basic_force_update - ) == SL_STATUS_OK) { - return true; - } + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); } - return false; + } -// Publishing Supported Commands for Basic Cluster -void uic_mqtt_dotdot_basic_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +static void uic_mqtt_dotdot_on_protocol_controller_network_management_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) { - std::stringstream ss; - bool first_command = true; - ss.str(""); + uint8_t endpoint = 0; + std::string unid; - // check if there is callback for each command - if (uic_mqtt_dotdot_basic_reset_to_factory_defaults_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ResetToFactoryDefaults")"; + if ((message_length == 0) || (uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.empty())) { + return; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_basic_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_basic_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } + try { + uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t force_update = {0}; + bool trigger_handler = false; - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Basic/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Basic/Attributes"; + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.network_management_state = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"NetworkManagementState", &force_update.network_management_state }, + }; + + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } + } + + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } } + } catch (...) { + sl_log_debug(LOG_TAG, "ProtocolController-NetworkManagement/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; } } -// Publishing empty/no Supported Commands for Basic Cluster -void uic_mqtt_dotdot_basic_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_protocol_controller_network_management_network_management_state_publish( + const char *base_topic, + NetworkManagementState value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Basic/SupportedCommands"; + nlohmann::json jsn; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + // This is a single value + + nlohmann::json json_object = nlohmann::json::object(); + json_object["State"] = value.State; + json_object["SupportedStateList"] = value.SupportedStateList; + json_object["StateParameters"] = value.StateParameters; + json_object["RequestedStateParameters"] = value.RequestedStateParameters; + jsn["value"]= json_object; + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "ProtocolController/NetworkManagement/Attributes/NetworkManagementState", e.what()); + return SL_STATUS_OK; } -} -// Publishing Cluster Revision for PowerConfiguration Cluster -void uic_mqtt_dotdot_power_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/PowerConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + + std::string topic = std::string(base_topic) + "/ProtocolController/NetworkManagement/Attributes/NetworkManagementState"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -// Unretain Cluster Revision for PowerConfiguration Cluster -void uic_mqtt_dotdot_power_configuration_unretain_cluster_revision(const char* base_topic) +sl_status_t uic_mqtt_dotdot_protocol_controller_network_management_network_management_state_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on - std::string cluster_topic + std::string topic = std::string(base_topic) - + "/PowerConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + + "/ProtocolController/NetworkManagement/Attributes/NetworkManagementState"; + + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } +// clang-format off -static inline bool uic_mqtt_dotdot_power_configuration_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_protocol_controller_network_management_init() { - for (const auto& callback: uic_mqtt_dotdot_power_configuration_write_attributes_callback) { - uic_mqtt_dotdot_power_configuration_state_t power_configuration_new_state = {}; - uic_mqtt_dotdot_power_configuration_updated_state_t power_configuration_new_updated_state = {}; + std::string base_topic = "ucl/by-unid/+/"; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - power_configuration_new_state, - power_configuration_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + std::string subscription_topic; + if(!uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback.empty()) { + subscription_topic = base_topic + "ProtocolController/NetworkManagement/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_protocol_controller_network_management_WriteAttributes); } - return false; -} -static inline bool uic_mqtt_dotdot_power_configuration_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_power_configuration_force_read_attributes_callback) { - uic_mqtt_dotdot_power_configuration_updated_state_t power_configuration_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - power_configuration_force_update - ) == SL_STATUS_OK) { - return true; - } + if(!uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "ProtocolController/NetworkManagement/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_protocol_controller_network_management_force_read_attributes); } - return false; + if (!uic_mqtt_dotdot_protocol_controller_network_management_write_callback.empty()) { + subscription_topic = base_topic + "ProtocolController/NetworkManagement/Commands/Write"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_protocol_controller_network_management_write); + } + if (!uic_mqtt_dotdot_protocol_controller_network_management_generated_write_callback.empty()) { + subscription_topic = base_topic + "ProtocolController/NetworkManagement/GeneratedCommands/Write"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_protocol_controller_network_management_write); + } + + // Init the attributes for that cluster + uic_mqtt_dotdot_protocol_controller_network_management_attributes_init(); + + + return SL_STATUS_OK; } -// Publishing Supported Commands for PowerConfiguration Cluster -void uic_mqtt_dotdot_power_configuration_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); +// Callbacks pointers +static std::set uic_mqtt_dotdot_descriptor_write_attributes_callback; +static std::set uic_mqtt_dotdot_descriptor_force_read_attributes_callback; - // check if there is callback for each command +// Callbacks setters - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_power_configuration_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_power_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PowerConfiguration/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/PowerConfiguration/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } +void uic_mqtt_dotdot_set_descriptor_write_attributes_callback( + const uic_mqtt_dotdot_descriptor_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_descriptor_write_attributes_callback.insert(callback); } } - -// Publishing empty/no Supported Commands for PowerConfiguration Cluster -void uic_mqtt_dotdot_power_configuration_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unset_descriptor_write_attributes_callback( + const uic_mqtt_dotdot_descriptor_write_attributes_callback_t callback) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PowerConfiguration/SupportedCommands"; + uic_mqtt_dotdot_descriptor_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_descriptor_write_attributes_callbacks() +{ + uic_mqtt_dotdot_descriptor_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_descriptor_write_attributes_callback() +{ + return uic_mqtt_dotdot_descriptor_write_attributes_callback; +} - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); +void uic_mqtt_dotdot_set_descriptor_force_read_attributes_callback( + const uic_mqtt_dotdot_descriptor_force_read_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_descriptor_force_read_attributes_callback.insert(callback); } } - -// Publishing Cluster Revision for DeviceTemperatureConfiguration Cluster -void uic_mqtt_dotdot_device_temperature_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) +void uic_mqtt_dotdot_unset_descriptor_force_read_attributes_callback( + const uic_mqtt_dotdot_descriptor_force_read_attributes_callback_t callback) { - std::string cluster_topic = std::string(base_topic) + "/DeviceTemperatureConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + uic_mqtt_dotdot_descriptor_force_read_attributes_callback.erase(callback); } - -// Unretain Cluster Revision for DeviceTemperatureConfiguration Cluster -void uic_mqtt_dotdot_device_temperature_configuration_unretain_cluster_revision(const char* base_topic) +void uic_mqtt_dotdot_clear_descriptor_force_read_attributes_callbacks() { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/DeviceTemperatureConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + uic_mqtt_dotdot_descriptor_force_read_attributes_callback.clear(); } -static inline bool uic_mqtt_dotdot_device_temperature_configuration_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// Callback function for incoming publications on ucl/by-unid/+/+/Descriptor/Commands/WriteAttributes +void uic_mqtt_dotdot_on_descriptor_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) { - for (const auto& callback: uic_mqtt_dotdot_device_temperature_configuration_write_attributes_callback) { - uic_mqtt_dotdot_device_temperature_configuration_state_t device_temperature_configuration_new_state = {}; - uic_mqtt_dotdot_device_temperature_configuration_updated_state_t device_temperature_configuration_new_updated_state = {}; + if (uic_mqtt_dotdot_descriptor_write_attributes_callback.empty()) { + return; + } - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - device_temperature_configuration_new_state, - device_temperature_configuration_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + if (message_length == 0) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_device_temperature_configuration_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_device_temperature_configuration_force_read_attributes_callback) { - uic_mqtt_dotdot_device_temperature_configuration_updated_state_t device_temperature_configuration_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - device_temperature_configuration_force_update - ) == SL_STATUS_OK) { - return true; - } + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return false; -} -// Publishing Supported Commands for DeviceTemperatureConfiguration Cluster -void uic_mqtt_dotdot_device_temperature_configuration_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); + uic_mqtt_dotdot_descriptor_state_t new_state = {}; + uic_mqtt_dotdot_descriptor_updated_state_t new_updated_state = {}; - // check if there is callback for each command - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_device_temperature_configuration_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_device_temperature_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + uic_mqtt_dotdot_parse_descriptor_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "Descriptor", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "Descriptor", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "Descriptor", "WriteAttributes", ""); + return; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/DeviceTemperatureConfiguration/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/DeviceTemperatureConfiguration/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + for (const auto& callback: uic_mqtt_dotdot_descriptor_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); } + } -// Publishing empty/no Supported Commands for DeviceTemperatureConfiguration Cluster -void uic_mqtt_dotdot_device_temperature_configuration_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static void uic_mqtt_dotdot_on_descriptor_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/DeviceTemperatureConfiguration/SupportedCommands"; + uint8_t endpoint = 0; + std::string unid; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if ((message_length == 0) || (uic_mqtt_dotdot_descriptor_force_read_attributes_callback.empty())) { + return; } -} -// Publishing Cluster Revision for Identify Cluster -void uic_mqtt_dotdot_identify_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Identify/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } -// Unretain Cluster Revision for Identify Cluster -void uic_mqtt_dotdot_identify_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Identify/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + try { + uic_mqtt_dotdot_descriptor_updated_state_t force_update = {0}; + bool trigger_handler = false; -static inline bool uic_mqtt_dotdot_identify_identify_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t identify_time_value; - memset(&identify_time_value, 0x00, sizeof(identify_time_value)); - for (const auto& callback: uic_mqtt_dotdot_identify_identify_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - identify_time_value - - ) == SL_STATUS_OK) { - return true; + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); + + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.device_type_list = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"DeviceTypeList", &force_update.device_type_list }, + }; + + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } } - } - return false; -} -static inline bool uic_mqtt_dotdot_identify_identify_query_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t timeout_value; - memset(&timeout_value, 0x00, sizeof(timeout_value)); - for (const auto& callback: uic_mqtt_dotdot_identify_identify_query_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - timeout_value - - ) == SL_STATUS_OK) { - return true; + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_descriptor_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } } + } catch (...) { + sl_log_debug(LOG_TAG, "Descriptor/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; } - - return false; } -static inline bool uic_mqtt_dotdot_identify_identify_query_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_descriptor_device_type_list_publish( + const char *base_topic, + size_t value_count, + const DeviceTypeStruct* value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - for (const auto& callback: uic_mqtt_dotdot_identify_identify_query_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a variable size array of the same known type. + // Create an array under the value {"value":[]} + jsn["value"] = nlohmann::json::array(); + + for (size_t i = 0; i uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback; +static std::set uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback; +static std::set uic_mqtt_dotdot_unify_fan_control_turn_off_callback; +static std::set uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback; +static std::set uic_mqtt_dotdot_unify_fan_control_write_attributes_callback; +static std::set uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback; - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } +// Callbacks setters +void uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_set(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.insert(callback); } } - -// Publishing empty/no Supported Commands for Identify Cluster -void uic_mqtt_dotdot_identify_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_unset(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Identify/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.erase(callback); } - -// Publishing Cluster Revision for Groups Cluster -void uic_mqtt_dotdot_groups_publish_cluster_revision(const char* base_topic, uint16_t value) +void uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_clear() { - std::string cluster_topic = std::string(base_topic) + "/Groups/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.clear(); } - -// Unretain Cluster Revision for Groups Cluster -void uic_mqtt_dotdot_groups_unretain_cluster_revision(const char* base_topic) +std::set& get_uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback() { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Groups/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback; } -static inline bool uic_mqtt_dotdot_groups_add_group_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback_set(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) { - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - const char* group_name_value; - memset(&group_name_value, 0x00, sizeof(group_name_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_add_group_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - group_id_value, - - group_name_value - - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.insert(callback); } - - return false; } -static inline bool uic_mqtt_dotdot_groups_add_group_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback_unset(const uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback_t callback) { - uint8_t status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_add_group_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - group_id_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.erase(callback); } -static inline bool uic_mqtt_dotdot_groups_view_group_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback_clear() { - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_view_group_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - group_id_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.clear(); } -static inline bool uic_mqtt_dotdot_groups_view_group_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_turn_off_callback_set(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) { - uint8_t status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - const char* group_name_value; - memset(&group_name_value, 0x00, sizeof(group_name_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_view_group_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - group_id_value, - - group_name_value - - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_fan_control_turn_off_callback.insert(callback); } - - return false; } -static inline bool uic_mqtt_dotdot_groups_get_group_membership_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_turn_off_callback_unset(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_groups_get_group_membership_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - 0, nullptr + uic_mqtt_dotdot_unify_fan_control_turn_off_callback.erase(callback); +} +void uic_mqtt_dotdot_unify_fan_control_turn_off_callback_clear() +{ + uic_mqtt_dotdot_unify_fan_control_turn_off_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_unify_fan_control_turn_off_callback() +{ + return uic_mqtt_dotdot_unify_fan_control_turn_off_callback; +} - ) == SL_STATUS_OK) { - return true; - } +void uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback_set(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.insert(callback); } - - return false; } -static inline bool uic_mqtt_dotdot_groups_get_group_membership_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback_unset(const uic_mqtt_dotdot_unify_fan_control_turn_off_callback_t callback) { - uint8_t capacity_value; - memset(&capacity_value, 0x00, sizeof(capacity_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_get_group_membership_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - capacity_value, - - 0, nullptr - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.erase(callback); } -static inline bool uic_mqtt_dotdot_groups_remove_group_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback_clear() { - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_remove_group_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - group_id_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.clear(); } -static inline bool uic_mqtt_dotdot_groups_remove_group_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +void uic_mqtt_dotdot_set_unify_fan_control_write_attributes_callback( + const uic_mqtt_dotdot_unify_fan_control_write_attributes_callback_t callback) { - uint8_t status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_remove_group_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - group_id_value - - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.insert(callback); } - - return false; } -static inline bool uic_mqtt_dotdot_groups_remove_all_groups_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unset_unify_fan_control_write_attributes_callback( + const uic_mqtt_dotdot_unify_fan_control_write_attributes_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_groups_remove_all_groups_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.erase(callback); } -static inline bool uic_mqtt_dotdot_groups_add_group_if_identifying_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_clear_unify_fan_control_write_attributes_callbacks() { - uint16_t group_id_value; - memset(&group_id_value, 0x00, sizeof(group_id_value)); - const char* group_name_value; - memset(&group_name_value, 0x00, sizeof(group_name_value)); - for (const auto& callback: uic_mqtt_dotdot_groups_add_group_if_identifying_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - group_id_value, - - group_name_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.clear(); } - -static inline bool uic_mqtt_dotdot_groups_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +std::set& get_uic_mqtt_dotdot_unify_fan_control_write_attributes_callback() { - for (const auto& callback: uic_mqtt_dotdot_groups_write_attributes_callback) { - uic_mqtt_dotdot_groups_state_t groups_new_state = {}; - uic_mqtt_dotdot_groups_updated_state_t groups_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - groups_new_state, - groups_new_updated_state - ) == SL_STATUS_OK) { - return true; - } - } - return false; + return uic_mqtt_dotdot_unify_fan_control_write_attributes_callback; } -static inline bool uic_mqtt_dotdot_groups_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_set_unify_fan_control_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_groups_force_read_attributes_callback) { - uic_mqtt_dotdot_groups_updated_state_t groups_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - groups_force_update - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.insert(callback); } - return false; +} +void uic_mqtt_dotdot_unset_unify_fan_control_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_unify_fan_control_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.clear(); } -// Publishing Supported Commands for Groups Cluster -void uic_mqtt_dotdot_groups_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/Commands/SetFanMode +void uic_mqtt_dotdot_on_unify_fan_control_set_fan_mode( + const char *topic, + const char *message, + const size_t message_length) { - std::stringstream ss; - bool first_command = true; - ss.str(""); + if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.empty())) { + return; + } - // check if there is callback for each command - if (uic_mqtt_dotdot_groups_add_group_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("AddGroup")"; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - if (uic_mqtt_dotdot_groups_add_group_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("AddGroupResponse")"; + + ZWaveFanModeEnum fan_mode = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_unify_fan_control_set_fan_mode( + jsn, + fan_mode + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "SetFanMode"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", ""); + return; } - if (uic_mqtt_dotdot_groups_view_group_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ViewGroup")"; + + + + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + fan_mode + + ); } - if (uic_mqtt_dotdot_groups_view_group_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ViewGroupResponse")"; + +} + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/GeneratedCommands/SetFanMode +static void uic_mqtt_dotdot_on_generated_unify_fan_control_set_fan_mode( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.empty())) { + return; } - if (uic_mqtt_dotdot_groups_get_group_membership_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetGroupMembership")"; - } - if (uic_mqtt_dotdot_groups_get_group_membership_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetGroupMembershipResponse")"; - } - if (uic_mqtt_dotdot_groups_remove_group_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveGroup")"; - } - if (uic_mqtt_dotdot_groups_remove_group_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveGroupResponse")"; - } - if (uic_mqtt_dotdot_groups_remove_all_groups_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveAllGroups")"; - } - if (uic_mqtt_dotdot_groups_add_group_if_identifying_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("AddGroupIfIdentifying")"; + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_groups_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } + ZWaveFanModeEnum fan_mode = {}; - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_groups_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_unify_fan_control_set_fan_mode( + jsn, + fan_mode + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "SetFanMode"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "SetFanMode", ""); + return; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Groups/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Groups/Attributes"; - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + + + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + fan_mode + + ); } } -// Publishing empty/no Supported Commands for Groups Cluster -void uic_mqtt_dotdot_groups_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/Commands/TurnOff +void uic_mqtt_dotdot_on_unify_fan_control_turn_off( + const char *topic, + const char *message, + const size_t message_length) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Groups/SupportedCommands"; + if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_turn_off_callback.empty())) { + return; + } - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } -} -// Publishing Cluster Revision for Scenes Cluster -void uic_mqtt_dotdot_scenes_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Scenes/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for Scenes Cluster -void uic_mqtt_dotdot_scenes_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Scenes/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} -static inline bool uic_mqtt_dotdot_scenes_add_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - SSceneName scene_name_value; - memset(&scene_name_value, 0x00, sizeof(scene_name_value)); - uint8_t transition_time100ms_value; - memset(&transition_time100ms_value, 0x00, sizeof(transition_time100ms_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_add_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value, - - transition_time_value, - - scene_name_value, - - 0, nullptr, + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - transition_time100ms_value - - ) == SL_STATUS_OK) { - return true; - } + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "TurnOff"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", ""); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_add_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_add_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } + + + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_turn_off_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); } - return false; } -static inline bool uic_mqtt_dotdot_scenes_view_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/GeneratedCommands/TurnOff +static void uic_mqtt_dotdot_on_generated_unify_fan_control_turn_off( + const char *topic, + const char *message, + const size_t message_length) { - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_view_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } + if (message_length == 0 || (uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.empty())) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_view_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - SSceneName scene_name_value; - memset(&scene_name_value, 0x00, sizeof(scene_name_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_view_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value, - - sceneid_value, - - transition_time_value, - - scene_name_value, - - 0, nullptr - - ) == SL_STATUS_OK) { - return true; - } + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_remove_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_remove_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "TurnOff"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "TurnOff", ""); + return; } - return false; + + + + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL + ); + } } -static inline bool uic_mqtt_dotdot_scenes_remove_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyFanControl/Commands/WriteAttributes +void uic_mqtt_dotdot_on_unify_fan_control_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) { - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_remove_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } + if (uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.empty()) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_remove_all_scenes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_remove_all_scenes_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value - - ) == SL_STATUS_OK) { - return true; - } + if (message_length == 0) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_remove_all_scenes_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_remove_all_scenes_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value - - ) == SL_STATUS_OK) { - return true; - } + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_store_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_store_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } + uic_mqtt_dotdot_unify_fan_control_state_t new_state = {}; + uic_mqtt_dotdot_unify_fan_control_updated_state_t new_updated_state = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_unify_fan_control_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyFanControl", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl", "WriteAttributes", ""); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_store_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_store_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); } - return false; } -static inline bool uic_mqtt_dotdot_scenes_recall_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +static void uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) { - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_recall_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value, - - transition_time_value - - ) == SL_STATUS_OK) { - return true; - } + uint8_t endpoint = 0; + std::string unid; + + if ((message_length == 0) || (uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.empty())) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_get_scene_membership_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_get_scene_membership_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value - - ) == SL_STATUS_OK) { - return true; - } + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_scenes_get_scene_membership_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint8_t capacity_value; - memset(&capacity_value, 0x00, sizeof(capacity_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_get_scene_membership_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - capacity_value, - - groupid_value, - - 0, nullptr + try { + uic_mqtt_dotdot_unify_fan_control_updated_state_t force_update = {0}; + bool trigger_handler = false; - ) == SL_STATUS_OK) { - return true; + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); + + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.z_wave_fan_mode = true; + force_update.z_wave_supported_fan_mode = true; + force_update.z_wave_fan_state = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"ZWaveFanMode", &force_update.z_wave_fan_mode }, + {"ZWaveSupportedFanMode", &force_update.z_wave_supported_fan_mode }, + {"ZWaveFanState", &force_update.z_wave_fan_state }, + }; + + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } } - } - return false; + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } + } + } catch (...) { + sl_log_debug(LOG_TAG, "UnifyFanControl/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; + } } -static inline bool uic_mqtt_dotdot_scenes_enhanced_add_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_publish( + const char *base_topic, + ZWaveFanModeEnum value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - SSceneName scene_name_value; - memset(&scene_name_value, 0x00, sizeof(scene_name_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_add_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value, - - transition_time_value, - - scene_name_value, - - 0, nullptr + nlohmann::json jsn; - ) == SL_STATUS_OK) { - return true; - } + // This is a single value + + #ifdef UNIFY_FAN_CONTROL_Z_WAVE_FAN_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_fan_control_z_wave_fan_mode_get_enum_value_name((uint32_t)value); + #elif defined(Z_WAVE_FAN_MODE_ENUM_ENUM_NAME_AVAILABLE) + jsn["value"] = z_wave_fan_mode_enum_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_FAN_CONTROL_Z_WAVE_FAN_MODE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl/Attributes/ZWaveFanMode", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ZWaveFanMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_scenes_enhanced_add_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_add_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyFanControl/Attributes/ZWaveFanMode"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_scenes_enhanced_view_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_view_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - groupid_value, - - sceneid_value - - ) == SL_STATUS_OK) { - return true; - } - } + nlohmann::json jsn; - return false; -} -static inline bool uic_mqtt_dotdot_scenes_enhanced_view_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId groupid_value; - memset(&groupid_value, 0x00, sizeof(groupid_value)); - uint8_t sceneid_value; - memset(&sceneid_value, 0x00, sizeof(sceneid_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - SSceneName scene_name_value; - memset(&scene_name_value, 0x00, sizeof(scene_name_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_view_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - groupid_value, - - sceneid_value, - - transition_time_value, - - scene_name_value, - - 0, nullptr + // This is a single value - ) == SL_STATUS_OK) { - return true; - } - } + nlohmann::json bitmap_values = UnifyFanControlZWaveSupportedFanMode.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; - return false; -} -static inline bool uic_mqtt_dotdot_scenes_copy_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t mode_value; - memset(&mode_value, 0x00, sizeof(mode_value)); - SGroupId group_identifier_from_value; - memset(&group_identifier_from_value, 0x00, sizeof(group_identifier_from_value)); - uint8_t scene_identifier_from_value; - memset(&scene_identifier_from_value, 0x00, sizeof(scene_identifier_from_value)); - SGroupId group_identifier_to_value; - memset(&group_identifier_to_value, 0x00, sizeof(group_identifier_to_value)); - uint8_t scene_identifier_to_value; - memset(&scene_identifier_to_value, 0x00, sizeof(scene_identifier_to_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_copy_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - mode_value, - - group_identifier_from_value, - - scene_identifier_from_value, - - group_identifier_to_value, - - scene_identifier_to_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl/Attributes/ZWaveSupportedFanMode", e.what()); + return SL_STATUS_OK; } - return false; + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); + + std::string topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ZWaveSupportedFanMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_scenes_copy_scene_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_supported_fan_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - SGroupId group_identifier_from_value; - memset(&group_identifier_from_value, 0x00, sizeof(group_identifier_from_value)); - uint8_t scene_identifier_from_value; - memset(&scene_identifier_from_value, 0x00, sizeof(scene_identifier_from_value)); - for (const auto& callback: uic_mqtt_dotdot_scenes_copy_scene_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - group_identifier_from_value, - - scene_identifier_from_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyFanControl/Attributes/ZWaveSupportedFanMode"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } +// clang-format off -static inline bool uic_mqtt_dotdot_scenes_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_publish( + const char *base_topic, + ZWaveFanStateEnum value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - for (const auto& callback: uic_mqtt_dotdot_scenes_write_attributes_callback) { - uic_mqtt_dotdot_scenes_state_t scenes_new_state = {}; - uic_mqtt_dotdot_scenes_updated_state_t scenes_new_updated_state = {}; + nlohmann::json jsn; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - scenes_new_state, - scenes_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + // This is a single value + + #ifdef UNIFY_FAN_CONTROL_Z_WAVE_FAN_STATE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_fan_control_z_wave_fan_state_get_enum_value_name((uint32_t)value); + #elif defined(Z_WAVE_FAN_STATE_ENUM_ENUM_NAME_AVAILABLE) + jsn["value"] = z_wave_fan_state_enum_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_FAN_CONTROL_Z_WAVE_FAN_STATE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyFanControl/Attributes/ZWaveFanState", e.what()); + return SL_STATUS_OK; } - return false; + + + std::string topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ZWaveFanState"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_scenes_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_fan_control_z_wave_fan_state_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - for (const auto& callback: uic_mqtt_dotdot_scenes_force_read_attributes_callback) { - uic_mqtt_dotdot_scenes_updated_state_t scenes_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - scenes_force_update - ) == SL_STATUS_OK) { - return true; - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyFanControl/Attributes/ZWaveFanState"; + + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } +// clang-format off -// Publishing Supported Commands for Scenes Cluster -void uic_mqtt_dotdot_scenes_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_fan_control_init() { - std::stringstream ss; - bool first_command = true; - ss.str(""); + std::string base_topic = "ucl/by-unid/+/+/"; - // check if there is callback for each command - if (uic_mqtt_dotdot_scenes_add_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("AddScene")"; + std::string subscription_topic; + if(!uic_mqtt_dotdot_unify_fan_control_write_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyFanControl/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_WriteAttributes); } - if (uic_mqtt_dotdot_scenes_add_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("AddSceneResponse")"; - } - if (uic_mqtt_dotdot_scenes_view_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ViewScene")"; - } - if (uic_mqtt_dotdot_scenes_view_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ViewSceneResponse")"; - } - if (uic_mqtt_dotdot_scenes_remove_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveScene")"; - } - if (uic_mqtt_dotdot_scenes_remove_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveSceneResponse")"; - } - if (uic_mqtt_dotdot_scenes_remove_all_scenes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveAllScenes")"; - } - if (uic_mqtt_dotdot_scenes_remove_all_scenes_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RemoveAllScenesResponse")"; - } - if (uic_mqtt_dotdot_scenes_store_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StoreScene")"; - } - if (uic_mqtt_dotdot_scenes_store_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StoreSceneResponse")"; - } - if (uic_mqtt_dotdot_scenes_recall_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("RecallScene")"; - } - if (uic_mqtt_dotdot_scenes_get_scene_membership_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetSceneMembership")"; - } - if (uic_mqtt_dotdot_scenes_get_scene_membership_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetSceneMembershipResponse")"; - } - if (uic_mqtt_dotdot_scenes_enhanced_add_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("EnhancedAddScene")"; - } - if (uic_mqtt_dotdot_scenes_enhanced_add_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("EnhancedAddSceneResponse")"; - } - if (uic_mqtt_dotdot_scenes_enhanced_view_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("EnhancedViewScene")"; + + if(!uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyFanControl/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_force_read_attributes); } - if (uic_mqtt_dotdot_scenes_enhanced_view_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("EnhancedViewSceneResponse")"; + if (!uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback.empty()) { + subscription_topic = base_topic + "UnifyFanControl/Commands/SetFanMode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_set_fan_mode); } - if (uic_mqtt_dotdot_scenes_copy_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("CopyScene")"; + if (!uic_mqtt_dotdot_unify_fan_control_generated_set_fan_mode_callback.empty()) { + subscription_topic = base_topic + "UnifyFanControl/GeneratedCommands/SetFanMode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_fan_control_set_fan_mode); } - if (uic_mqtt_dotdot_scenes_copy_scene_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("CopySceneResponse")"; + if (!uic_mqtt_dotdot_unify_fan_control_turn_off_callback.empty()) { + subscription_topic = base_topic + "UnifyFanControl/Commands/TurnOff"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_fan_control_turn_off); } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_scenes_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; + if (!uic_mqtt_dotdot_unify_fan_control_generated_turn_off_callback.empty()) { + subscription_topic = base_topic + "UnifyFanControl/GeneratedCommands/TurnOff"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_fan_control_turn_off); } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_scenes_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } + // Init the attributes for that cluster + uic_mqtt_dotdot_unify_fan_control_attributes_init(); - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Scenes/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Scenes/Attributes"; + uic_mqtt_dotdot_by_group_unify_fan_control_init(); - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return SL_STATUS_OK; } -// Publishing empty/no Supported Commands for Scenes Cluster -void uic_mqtt_dotdot_scenes_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Scenes/SupportedCommands"; +// Callbacks pointers +static std::set uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; +static std::set uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); +// Callbacks setters + +void uic_mqtt_dotdot_set_unify_thermostat_write_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.insert(callback); } } - -// Publishing Cluster Revision for OnOff Cluster -void uic_mqtt_dotdot_on_off_publish_cluster_revision(const char* base_topic, uint16_t value) +void uic_mqtt_dotdot_unset_unify_thermostat_write_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_write_attributes_callback_t callback) { - std::string cluster_topic = std::string(base_topic) + "/OnOff/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.erase(callback); } - -// Unretain Cluster Revision for OnOff Cluster -void uic_mqtt_dotdot_on_off_unretain_cluster_revision(const char* base_topic) +void uic_mqtt_dotdot_clear_unify_thermostat_write_attributes_callbacks() { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/OnOff/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.clear(); } - -static inline bool uic_mqtt_dotdot_on_off_off_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +std::set& get_uic_mqtt_dotdot_unify_thermostat_write_attributes_callback() { - for (const auto& callback: uic_mqtt_dotdot_on_off_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + return uic_mqtt_dotdot_unify_thermostat_write_attributes_callback; } -static inline bool uic_mqtt_dotdot_on_off_on_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +void uic_mqtt_dotdot_set_unify_thermostat_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_on_off_on_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.insert(callback); } - - return false; } -static inline bool uic_mqtt_dotdot_on_off_toggle_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unset_unify_thermostat_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_on_off_toggle_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.erase(callback); } -static inline bool uic_mqtt_dotdot_on_off_off_with_effect_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_clear_unify_thermostat_force_read_attributes_callbacks() { - OffWithEffectEffectIdentifier effect_identifier_value; - memset(&effect_identifier_value, 0x00, sizeof(effect_identifier_value)); - uint8_t effect_variant_value; - memset(&effect_variant_value, 0x00, sizeof(effect_variant_value)); - for (const auto& callback: uic_mqtt_dotdot_on_off_off_with_effect_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - effect_identifier_value, - - effect_variant_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; + uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.clear(); } -static inline bool uic_mqtt_dotdot_on_off_on_with_recall_global_scene_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyThermostat/Commands/WriteAttributes +void uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) { - for (const auto& callback: uic_mqtt_dotdot_on_off_on_with_recall_global_scene_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if (uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.empty()) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_on_off_on_with_timed_off_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t on_off_control_value; - memset(&on_off_control_value, 0x00, sizeof(on_off_control_value)); - uint16_t on_time_value; - memset(&on_time_value, 0x00, sizeof(on_time_value)); - uint16_t off_wait_time_value; - memset(&off_wait_time_value, 0x00, sizeof(off_wait_time_value)); - for (const auto& callback: uic_mqtt_dotdot_on_off_on_with_timed_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - on_off_control_value, - - on_time_value, - - off_wait_time_value - - ) == SL_STATUS_OK) { - return true; - } + if (message_length == 0) { + return; } - return false; -} + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } -static inline bool uic_mqtt_dotdot_on_off_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_on_off_write_attributes_callback) { - uic_mqtt_dotdot_on_off_state_t on_off_new_state = {}; - uic_mqtt_dotdot_on_off_updated_state_t on_off_new_updated_state = {}; + uic_mqtt_dotdot_unify_thermostat_state_t new_state = {}; + uic_mqtt_dotdot_unify_thermostat_updated_state_t new_updated_state = {}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - on_off_new_state, - on_off_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_unify_thermostat_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyThermostat", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat", "WriteAttributes", ""); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_on_off_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_on_off_force_read_attributes_callback) { - uic_mqtt_dotdot_on_off_updated_state_t on_off_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - on_off_force_update - ) == SL_STATUS_OK) { - return true; - } + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); } - return false; + } -// Publishing Supported Commands for OnOff Cluster -void uic_mqtt_dotdot_on_off_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +static void uic_mqtt_dotdot_on_unify_thermostat_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) { - std::stringstream ss; - bool first_command = true; - ss.str(""); + uint8_t endpoint = 0; + std::string unid; - // check if there is callback for each command - if (uic_mqtt_dotdot_on_off_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Off")"; - } - if (uic_mqtt_dotdot_on_off_on_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("On")"; - } - if (uic_mqtt_dotdot_on_off_toggle_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Toggle")"; - } - if (uic_mqtt_dotdot_on_off_off_with_effect_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("OffWithEffect")"; - } - if (uic_mqtt_dotdot_on_off_on_with_recall_global_scene_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("OnWithRecallGlobalScene")"; - } - if (uic_mqtt_dotdot_on_off_on_with_timed_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("OnWithTimedOff")"; + if ((message_length == 0) || (uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.empty())) { + return; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_on_off_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_on_off_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } + try { + uic_mqtt_dotdot_unify_thermostat_updated_state_t force_update = {0}; + bool trigger_handler = false; - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/OnOff/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/OnOff/Attributes"; + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.thermostat_mode = true; + force_update.supported_thermostat_mode = true; + force_update.operating_state = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"ThermostatMode", &force_update.thermostat_mode }, + {"SupportedThermostatMode", &force_update.supported_thermostat_mode }, + {"OperatingState", &force_update.operating_state }, + }; + + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } + } + + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } } + } catch (...) { + sl_log_debug(LOG_TAG, "UnifyThermostat/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; } } -// Publishing empty/no Supported Commands for OnOff Cluster -void uic_mqtt_dotdot_on_off_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/OnOff/SupportedCommands"; + nlohmann::json jsn; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + // This is a single value + + #ifdef UNIFY_THERMOSTAT_THERMOSTAT_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_thermostat_thermostat_mode_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_THERMOSTAT_THERMOSTAT_MODE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/ThermostatMode", e.what()); + return SL_STATUS_OK; } -} -// Publishing Cluster Revision for Level Cluster -void uic_mqtt_dotdot_level_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Level/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + + std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/ThermostatMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -// Unretain Cluster Revision for Level Cluster -void uic_mqtt_dotdot_level_unretain_cluster_revision(const char* base_topic) +sl_status_t uic_mqtt_dotdot_unify_thermostat_thermostat_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on - std::string cluster_topic + std::string topic = std::string(base_topic) - + "/Level/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + + "/UnifyThermostat/Attributes/ThermostatMode"; -static inline bool uic_mqtt_dotdot_level_move_to_level_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t level_value; - memset(&level_value, 0x00, sizeof(level_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_move_to_level_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - level_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } - - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_level_move_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_publish( + const char *base_topic, + uint16_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - MoveStepMode move_mode_value; - memset(&move_mode_value, 0x00, sizeof(move_mode_value)); - uint8_t rate_value; - memset(&rate_value, 0x00, sizeof(rate_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_move_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - move_mode_value, - - rate_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + nlohmann::json bitmap_values = UnifyThermostatSupportedThermostatMode.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/SupportedThermostatMode", e.what()); + return SL_STATUS_OK; } - return false; + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); + + std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/SupportedThermostatMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_level_step_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - MoveStepMode step_mode_value; - memset(&step_mode_value, 0x00, sizeof(step_mode_value)); - uint8_t step_size_value; - memset(&step_size_value, 0x00, sizeof(step_size_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_step_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - step_mode_value, - - step_size_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} -static inline bool uic_mqtt_dotdot_level_stop_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_thermostat_supported_thermostat_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_stop_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyThermostat/Attributes/SupportedThermostatMode"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_level_move_to_level_with_on_off_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - uint8_t level_value; - memset(&level_value, 0x00, sizeof(level_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_move_to_level_with_on_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - level_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + #ifdef UNIFY_THERMOSTAT_OPERATING_STATE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_thermostat_operating_state_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_THERMOSTAT_OPERATING_STATE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyThermostat/Attributes/OperatingState", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyThermostat/Attributes/OperatingState"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_level_move_with_on_off_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_thermostat_operating_state_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - MoveStepMode move_mode_value; - memset(&move_mode_value, 0x00, sizeof(move_mode_value)); - uint8_t rate_value; - memset(&rate_value, 0x00, sizeof(rate_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_move_with_on_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - move_mode_value, - - rate_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyThermostat/Attributes/OperatingState"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_level_step_with_on_off_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + + +sl_status_t uic_mqtt_dotdot_unify_thermostat_init() { - MoveStepMode step_mode_value; - memset(&step_mode_value, 0x00, sizeof(step_mode_value)); - uint8_t step_size_value; - memset(&step_size_value, 0x00, sizeof(step_size_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_step_with_on_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - step_mode_value, - - step_size_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } + std::string base_topic = "ucl/by-unid/+/+/"; + + std::string subscription_topic; + if(!uic_mqtt_dotdot_unify_thermostat_write_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyThermostat/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_thermostat_WriteAttributes); } - return false; -} -static inline bool uic_mqtt_dotdot_level_stop_with_on_off_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_level_stop_with_on_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } + if(!uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyThermostat/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_thermostat_force_read_attributes); } - return false; + // Init the attributes for that cluster + uic_mqtt_dotdot_unify_thermostat_attributes_init(); + + uic_mqtt_dotdot_by_group_unify_thermostat_init(); + + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_level_move_to_closest_frequency_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +// Callbacks pointers +static std::set uic_mqtt_dotdot_unify_humidity_control_mode_set_callback; +static std::set uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback; +static std::set uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback; +static std::set uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback; +static std::set uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback; +static std::set uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback; + +// Callbacks setters +void uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) { - uint16_t frequency_value; - memset(&frequency_value, 0x00, sizeof(frequency_value)); - for (const auto& callback: uic_mqtt_dotdot_level_move_to_closest_frequency_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - frequency_value - - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.insert(callback); } +} +void uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +{ + uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.erase(callback); +} +void uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_clear() +{ + uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_unify_humidity_control_mode_set_callback() +{ + return uic_mqtt_dotdot_unify_humidity_control_mode_set_callback; +} - return false; +void uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_mode_set_callback_t callback) +{ + uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.erase(callback); +} +void uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback_clear() +{ + uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.clear(); +} +void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +{ + uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.erase(callback); +} +void uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_clear() +{ + uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback() +{ + return uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback; } -static inline bool uic_mqtt_dotdot_level_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback_set(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_level_write_attributes_callback) { - uic_mqtt_dotdot_level_state_t level_new_state = {}; - uic_mqtt_dotdot_level_updated_state_t level_new_updated_state = {}; + if (callback != nullptr) { + uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.insert(callback); + } +} +void uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback_unset(const uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback_t callback) +{ + uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.erase(callback); +} +void uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback_clear() +{ + uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.clear(); +} - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - level_new_state, - level_new_updated_state - ) == SL_STATUS_OK) { - return true; - } +void uic_mqtt_dotdot_set_unify_humidity_control_write_attributes_callback( + const uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback_t callback) +{ + if (callback != nullptr) { + uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.insert(callback); } - return false; +} +void uic_mqtt_dotdot_unset_unify_humidity_control_write_attributes_callback( + const uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_unify_humidity_control_write_attributes_callbacks() +{ + uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.clear(); +} +std::set& get_uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback() +{ + return uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback; } -static inline bool uic_mqtt_dotdot_level_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +void uic_mqtt_dotdot_set_unify_humidity_control_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback_t callback) { - for (const auto& callback: uic_mqtt_dotdot_level_force_read_attributes_callback) { - uic_mqtt_dotdot_level_updated_state_t level_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - level_force_update - ) == SL_STATUS_OK) { - return true; - } + if (callback != nullptr) { + uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.insert(callback); } - return false; +} +void uic_mqtt_dotdot_unset_unify_humidity_control_force_read_attributes_callback( + const uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback_t callback) +{ + uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.erase(callback); +} +void uic_mqtt_dotdot_clear_unify_humidity_control_force_read_attributes_callbacks() +{ + uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.clear(); } -// Publishing Supported Commands for Level Cluster -void uic_mqtt_dotdot_level_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/Commands/ModeSet +void uic_mqtt_dotdot_on_unify_humidity_control_mode_set( + const char *topic, + const char *message, + const size_t message_length) { - std::stringstream ss; - bool first_command = true; - ss.str(""); + if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.empty())) { + return; + } - // check if there is callback for each command - if (uic_mqtt_dotdot_level_move_to_level_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveToLevel")"; + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - if (uic_mqtt_dotdot_level_move_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Move")"; + + ModeType mode = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_unify_humidity_control_mode_set( + jsn, + mode + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "ModeSet"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", ""); + return; } - if (uic_mqtt_dotdot_level_step_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Step")"; + + + + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_mode_set_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + mode + + ); } - if (uic_mqtt_dotdot_level_stop_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Stop")"; + +} + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/GeneratedCommands/ModeSet +static void uic_mqtt_dotdot_on_generated_unify_humidity_control_mode_set( + const char *topic, + const char *message, + const size_t message_length) +{ + if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.empty())) { + return; } - if (uic_mqtt_dotdot_level_move_to_level_with_on_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveToLevelWithOnOff")"; - } - if (uic_mqtt_dotdot_level_move_with_on_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveWithOnOff")"; - } - if (uic_mqtt_dotdot_level_step_with_on_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StepWithOnOff")"; - } - if (uic_mqtt_dotdot_level_stop_with_on_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StopWithOnOff")"; - } - if (uic_mqtt_dotdot_level_move_to_closest_frequency_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveToClosestFrequency")"; + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_level_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } + ModeType mode = {}; - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_level_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Level/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Level/Attributes"; + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + + uic_mqtt_dotdot_parse_unify_humidity_control_mode_set( + jsn, + mode + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "ModeSet"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "ModeSet", ""); + return; } -} -// Publishing empty/no Supported Commands for Level Cluster -void uic_mqtt_dotdot_level_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Level/SupportedCommands"; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + + + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + mode + + ); } } -// Publishing Cluster Revision for Alarms Cluster -void uic_mqtt_dotdot_alarms_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Alarms/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for Alarms Cluster -void uic_mqtt_dotdot_alarms_unretain_cluster_revision(const char* base_topic) +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/Commands/SetpointSet +void uic_mqtt_dotdot_on_unify_humidity_control_setpoint_set( + const char *topic, + const char *message, + const size_t message_length) { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Alarms/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.empty())) { + return; + } -static inline bool uic_mqtt_dotdot_alarms_reset_alarm_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t alarm_code_value; - memset(&alarm_code_value, 0x00, sizeof(alarm_code_value)); - clusterId cluster_identifier_value; - memset(&cluster_identifier_value, 0x00, sizeof(cluster_identifier_value)); - for (const auto& callback: uic_mqtt_dotdot_alarms_reset_alarm_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - alarm_code_value, - - cluster_identifier_value - - ) == SL_STATUS_OK) { - return true; - } + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_alarms_alarm_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t alarm_code_value; - memset(&alarm_code_value, 0x00, sizeof(alarm_code_value)); - clusterId cluster_identifier_value; - memset(&cluster_identifier_value, 0x00, sizeof(cluster_identifier_value)); - for (const auto& callback: uic_mqtt_dotdot_alarms_alarm_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - alarm_code_value, - - cluster_identifier_value - - ) == SL_STATUS_OK) { - return true; - } + SetpointType type = {}; + uint8_t precision = {}; + uint8_t scale = {}; + int32_t value = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_unify_humidity_control_setpoint_set( + jsn, + type, + + precision, + + scale, + + value + ); + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "SetpointSet"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", ""); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_alarms_reset_all_alarms_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_alarms_reset_all_alarms_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + + + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + type, + + precision, + + scale, + + value + + ); } - return false; } -static inline bool uic_mqtt_dotdot_alarms_get_alarm_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint8_t alarm_code_value; - memset(&alarm_code_value, 0x00, sizeof(alarm_code_value)); - clusterId cluster_identifier_value; - memset(&cluster_identifier_value, 0x00, sizeof(cluster_identifier_value)); - uint32_t time_stamp_value; - memset(&time_stamp_value, 0x00, sizeof(time_stamp_value)); - for (const auto& callback: uic_mqtt_dotdot_alarms_get_alarm_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value, - - alarm_code_value, - - cluster_identifier_value, - - time_stamp_value - - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} -static inline bool uic_mqtt_dotdot_alarms_get_alarm_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/GeneratedCommands/SetpointSet +static void uic_mqtt_dotdot_on_generated_unify_humidity_control_setpoint_set( + const char *topic, + const char *message, + const size_t message_length) { - for (const auto& callback: uic_mqtt_dotdot_alarms_get_alarm_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if (message_length == 0 || (uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.empty())) { + return; } - return false; -} -static inline bool uic_mqtt_dotdot_alarms_reset_alarm_log_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_alarms_reset_alarm_log_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - return false; -} + SetpointType type = {}; + uint8_t precision = {}; + uint8_t scale = {}; + int32_t value = {}; -static inline bool uic_mqtt_dotdot_alarms_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_alarms_write_attributes_callback) { - uic_mqtt_dotdot_alarms_state_t alarms_new_state = {}; - uic_mqtt_dotdot_alarms_updated_state_t alarms_new_updated_state = {}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - alarms_new_state, - alarms_new_updated_state - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); -static inline bool uic_mqtt_dotdot_alarms_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_alarms_force_read_attributes_callback) { - uic_mqtt_dotdot_alarms_updated_state_t alarms_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - alarms_force_update - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} + + uic_mqtt_dotdot_parse_unify_humidity_control_setpoint_set( + jsn, + type, -// Publishing Supported Commands for Alarms Cluster -void uic_mqtt_dotdot_alarms_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); + precision, - // check if there is callback for each command - if (uic_mqtt_dotdot_alarms_reset_alarm_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ResetAlarm")"; - } - if (uic_mqtt_dotdot_alarms_alarm_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Alarm")"; - } - if (uic_mqtt_dotdot_alarms_reset_all_alarms_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ResetAllAlarms")"; - } - if (uic_mqtt_dotdot_alarms_get_alarm_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetAlarmResponse")"; - } - if (uic_mqtt_dotdot_alarms_get_alarm_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetAlarm")"; - } - if (uic_mqtt_dotdot_alarms_reset_alarm_log_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ResetAlarmLog")"; - } + scale, - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_alarms_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } + value + ); - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_alarms_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "SetpointSet"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "SetpointSet", ""); + return; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Alarms/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Alarms/Attributes"; - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + + + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + type, + + precision, + + scale, + + value + + ); } } -// Publishing empty/no Supported Commands for Alarms Cluster -void uic_mqtt_dotdot_alarms_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) + +// Callback function for incoming publications on ucl/by-unid/+/+/UnifyHumidityControl/Commands/WriteAttributes +void uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Alarms/SupportedCommands"; + if (uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.empty()) { + return; + } - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (message_length == 0) { + return; } -} -// Publishing Cluster Revision for Time Cluster -void uic_mqtt_dotdot_time_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Time/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } -// Unretain Cluster Revision for Time Cluster -void uic_mqtt_dotdot_time_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Time/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + uic_mqtt_dotdot_unify_humidity_control_state_t new_state = {}; + uic_mqtt_dotdot_unify_humidity_control_updated_state_t new_updated_state = {}; -static inline bool uic_mqtt_dotdot_time_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_time_write_attributes_callback) { - uic_mqtt_dotdot_time_state_t time_new_state = {}; - uic_mqtt_dotdot_time_updated_state_t time_new_updated_state = {}; + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - time_new_state, - time_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + uic_mqtt_dotdot_parse_unify_humidity_control_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UnifyHumidityControl", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl", "WriteAttributes", ""); + return; } - return false; -} -static inline bool uic_mqtt_dotdot_time_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_time_force_read_attributes_callback) { - uic_mqtt_dotdot_time_updated_state_t time_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - time_force_update - ) == SL_STATUS_OK) { - return true; - } + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback){ + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + new_state, + new_updated_state + ); } - return false; + } -// Publishing Supported Commands for Time Cluster -void uic_mqtt_dotdot_time_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +static void uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes( + const char *topic, + const char *message, + const size_t message_length) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command + uint8_t endpoint = 0; + std::string unid; - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_time_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; + if ((message_length == 0) || (uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.empty())) { + return; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_time_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + if(! uic_dotdot_mqtt::parse_topic(topic, unid, endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Time/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Time/Attributes"; + try { + uic_mqtt_dotdot_unify_humidity_control_updated_state_t force_update = {0}; + bool trigger_handler = false; - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + std::vector attributes = jsn["value"].get>(); + + // Assume all attributes to be read on empty array received + if (attributes.size() == 0) { + force_update.reporting_mode = true; + force_update.supported_reporting_mode = true; + force_update.current_state = true; + force_update.supported_set_points = true; + force_update.humidifier_setpoint_min = true; + force_update.humidifier_setpoint_max = true; + force_update.humidifier_setpoint = true; + force_update.humidifier_setpoint_scale = true; + force_update.humidifier_setpoint_precision = true; + force_update.dehumidifier_setpoint_min = true; + force_update.dehumidifier_setpoint_max = true; + force_update.dehumidifier_setpoint = true; + force_update.dehumidifier_setpoint_scale = true; + force_update.dehumidifier_setpoint_precision = true; + force_update.auto_setpoint_min = true; + force_update.auto_setpoint_max = true; + force_update.auto_setpoint = true; + force_update.auto_setpoint_scale = true; + force_update.auto_setpoint_precision = true; + trigger_handler = true; + } else { + std::unordered_map supported_attrs = { + {"ReportingMode", &force_update.reporting_mode }, + {"SupportedReportingMode", &force_update.supported_reporting_mode }, + {"CurrentState", &force_update.current_state }, + {"SupportedSetPoints", &force_update.supported_set_points }, + {"HumidifierSetpointMin", &force_update.humidifier_setpoint_min }, + {"HumidifierSetpointMax", &force_update.humidifier_setpoint_max }, + {"HumidifierSetpoint", &force_update.humidifier_setpoint }, + {"HumidifierSetpointScale", &force_update.humidifier_setpoint_scale }, + {"HumidifierSetpointPrecision", &force_update.humidifier_setpoint_precision }, + {"DehumidifierSetpointMin", &force_update.dehumidifier_setpoint_min }, + {"DehumidifierSetpointMax", &force_update.dehumidifier_setpoint_max }, + {"DehumidifierSetpoint", &force_update.dehumidifier_setpoint }, + {"DehumidifierSetpointScale", &force_update.dehumidifier_setpoint_scale }, + {"DehumidifierSetpointPrecision", &force_update.dehumidifier_setpoint_precision }, + {"AutoSetpointMin", &force_update.auto_setpoint_min }, + {"AutoSetpointMax", &force_update.auto_setpoint_max }, + {"AutoSetpoint", &force_update.auto_setpoint }, + {"AutoSetpointScale", &force_update.auto_setpoint_scale }, + {"AutoSetpointPrecision", &force_update.auto_setpoint_precision }, + }; + + for (auto& attribute : attributes) { + auto found_attr = supported_attrs.find(attribute); + if (found_attr != supported_attrs.end()) { + *(found_attr->second) = true; + trigger_handler = true; + } + } + } + + if (trigger_handler == true) { + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback) { + callback( + static_cast(unid.c_str()), + endpoint, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_NORMAL, + force_update + ); + } } + } catch (...) { + sl_log_debug(LOG_TAG, "UnifyHumidityControl/Commands/ForceReadAttributes: Unable to parse JSON payload"); + return; } } -// Publishing empty/no Supported Commands for Time Cluster -void uic_mqtt_dotdot_time_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_publish( + const char *base_topic, + ModeType value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Time/SupportedCommands"; + nlohmann::json jsn; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } -} + // This is a single value -// Publishing Cluster Revision for PollControl Cluster -void uic_mqtt_dotdot_poll_control_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/PollControl/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + #ifdef UNIFY_HUMIDITY_CONTROL_REPORTING_MODE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_humidity_control_reporting_mode_get_enum_value_name((uint32_t)value); + #elif defined(MODE_TYPE_ENUM_NAME_AVAILABLE) + jsn["value"] = mode_type_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_REPORTING_MODE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/ReportingMode", e.what()); + return SL_STATUS_OK; + } + + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/ReportingMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -// Unretain Cluster Revision for PollControl Cluster -void uic_mqtt_dotdot_poll_control_unretain_cluster_revision(const char* base_topic) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_reporting_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on - std::string cluster_topic + std::string topic = std::string(base_topic) - + "/PollControl/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + + "/UnifyHumidityControl/Attributes/ReportingMode"; -static inline bool uic_mqtt_dotdot_poll_control_check_in_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_poll_control_check_in_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } - - return false; -} -static inline bool uic_mqtt_dotdot_poll_control_check_in_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - bool start_fast_polling_value; - memset(&start_fast_polling_value, 0x00, sizeof(start_fast_polling_value)); - uint16_t fast_poll_timeout_value; - memset(&fast_poll_timeout_value, 0x00, sizeof(fast_poll_timeout_value)); - for (const auto& callback: uic_mqtt_dotdot_poll_control_check_in_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - start_fast_polling_value, - - fast_poll_timeout_value - - ) == SL_STATUS_OK) { - return true; - } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); } - - return false; + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_poll_control_fast_poll_stop_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_poll_control_fast_poll_stop_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } +// clang-format off - return false; -} -static inline bool uic_mqtt_dotdot_poll_control_set_long_poll_interval_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - uint32_t new_long_poll_interval_value; - memset(&new_long_poll_interval_value, 0x00, sizeof(new_long_poll_interval_value)); - for (const auto& callback: uic_mqtt_dotdot_poll_control_set_long_poll_interval_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - new_long_poll_interval_value - - ) == SL_STATUS_OK) { - return true; - } - } + nlohmann::json jsn; - return false; -} -static inline bool uic_mqtt_dotdot_poll_control_set_short_poll_interval_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t new_short_poll_interval_value; - memset(&new_short_poll_interval_value, 0x00, sizeof(new_short_poll_interval_value)); - for (const auto& callback: uic_mqtt_dotdot_poll_control_set_short_poll_interval_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - new_short_poll_interval_value - - ) == SL_STATUS_OK) { - return true; - } - } + // This is a single value - return false; -} + nlohmann::json bitmap_values = UnifyHumidityControlSupportedReportingMode.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; -static inline bool uic_mqtt_dotdot_poll_control_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_poll_control_write_attributes_callback) { - uic_mqtt_dotdot_poll_control_state_t poll_control_new_state = {}; - uic_mqtt_dotdot_poll_control_updated_state_t poll_control_new_updated_state = {}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - poll_control_new_state, - poll_control_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/SupportedReportingMode", e.what()); + return SL_STATUS_OK; } - return false; -} -static inline bool uic_mqtt_dotdot_poll_control_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_poll_control_force_read_attributes_callback) { - uic_mqtt_dotdot_poll_control_updated_state_t poll_control_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - poll_control_force_update - ) == SL_STATUS_OK) { - return true; - } + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/SupportedReportingMode"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } - return false; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -// Publishing Supported Commands for PollControl Cluster -void uic_mqtt_dotdot_poll_control_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_reporting_mode_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - std::stringstream ss; - bool first_command = true; - ss.str(""); + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/SupportedReportingMode"; - // check if there is callback for each command - if (uic_mqtt_dotdot_poll_control_check_in_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("CheckIn")"; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } - if (uic_mqtt_dotdot_poll_control_check_in_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("CheckInResponse")"; - } - if (uic_mqtt_dotdot_poll_control_fast_poll_stop_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("FastPollStop")"; - } - if (uic_mqtt_dotdot_poll_control_set_long_poll_interval_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetLongPollInterval")"; - } - if (uic_mqtt_dotdot_poll_control_set_short_poll_interval_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetShortPollInterval")"; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); } + return SL_STATUS_OK; +} +// clang-format off - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_poll_control_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } +sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) +{ + nlohmann::json jsn; - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_poll_control_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } + // This is a single value - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PollControl/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/PollControl/Attributes"; + #ifdef UNIFY_HUMIDITY_CONTROL_CURRENT_STATE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_humidity_control_current_state_get_enum_value_name((uint32_t)value); + #elif defined(ENUM8_ENUM_NAME_AVAILABLE) + jsn["value"] = enum8_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_CURRENT_STATE. Using number instead."); + jsn["value"] = static_cast(value); + #endif - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/CurrentState", e.what()); + return SL_STATUS_OK; } -} -// Publishing empty/no Supported Commands for PollControl Cluster -void uic_mqtt_dotdot_poll_control_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PollControl/SupportedCommands"; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/CurrentState"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -// Publishing Cluster Revision for ShadeConfiguration Cluster -void uic_mqtt_dotdot_shade_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/ShadeConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for ShadeConfiguration Cluster -void uic_mqtt_dotdot_shade_configuration_unretain_cluster_revision(const char* base_topic) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_current_state_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { // clang-format on - std::string cluster_topic + std::string topic = std::string(base_topic) - + "/ShadeConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - - -static inline bool uic_mqtt_dotdot_shade_configuration_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_shade_configuration_write_attributes_callback) { - uic_mqtt_dotdot_shade_configuration_state_t shade_configuration_new_state = {}; - uic_mqtt_dotdot_shade_configuration_updated_state_t shade_configuration_new_updated_state = {}; + + "/UnifyHumidityControl/Attributes/CurrentState"; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - shade_configuration_new_state, - shade_configuration_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } - return false; -} - -static inline bool uic_mqtt_dotdot_shade_configuration_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_shade_configuration_force_read_attributes_callback) { - uic_mqtt_dotdot_shade_configuration_updated_state_t shade_configuration_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - shade_configuration_force_update - ) == SL_STATUS_OK) { - return true; - } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); } - return false; + return SL_STATUS_OK; } +// clang-format off -// Publishing Supported Commands for ShadeConfiguration Cluster -void uic_mqtt_dotdot_shade_configuration_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_set_points_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - std::stringstream ss; - bool first_command = true; - ss.str(""); + nlohmann::json jsn; - // check if there is callback for each command + // This is a single value - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_shade_configuration_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } + nlohmann::json bitmap_values = UnifyHumidityControlSupportedSetPoints.get_bitmap_values_as_json_tree((uint32_t)value); + jsn["value"] = bitmap_values; - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_shade_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/SupportedSetPoints", e.what()); + return SL_STATUS_OK; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ShadeConfiguration/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/ShadeConfiguration/Attributes"; + boost::replace_all(payload_str, "\"true\"", "true"); + boost::replace_all(payload_str, "\"false\"", "false"); - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/SupportedSetPoints"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } + return SL_STATUS_OK; } -// Publishing empty/no Supported Commands for ShadeConfiguration Cluster -void uic_mqtt_dotdot_shade_configuration_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_supported_set_points_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ShadeConfiguration/SupportedCommands"; + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/SupportedSetPoints"; - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } +// clang-format off -// Publishing Cluster Revision for DoorLock Cluster -void uic_mqtt_dotdot_door_lock_publish_cluster_revision(const char* base_topic, uint16_t value) +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_min_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - std::string cluster_topic = std::string(base_topic) + "/DoorLock/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} + nlohmann::json jsn; -// Unretain Cluster Revision for DoorLock Cluster -void uic_mqtt_dotdot_door_lock_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/DoorLock/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + // This is a single value -static inline bool uic_mqtt_dotdot_door_lock_lock_door_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* pin_or_rfid_code_value; - memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_lock_door_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - pin_or_rfid_code_value - - ) == SL_STATUS_OK) { - return true; - } + if (true == uic_dotdot_has_attribute_value_a_name(64928,5,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,5,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_lock_door_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_lock_door_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpointMin", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpointMin"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_unlock_door_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_min_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - const char* pin_or_rfid_code_value; - memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_door_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - pin_or_rfid_code_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/HumidifierSetpointMin"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_unlock_door_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_max_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_door_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,6,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,6,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_toggle_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* pin_or_rfid_code_value; - memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_toggle_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - pin_or_rfid_code_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpointMax", e.what()); + return SL_STATUS_OK; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_toggle_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_toggle_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_unlock_with_timeout_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t timeout_in_seconds_value; - memset(&timeout_in_seconds_value, 0x00, sizeof(timeout_in_seconds_value)); - const char* pin_or_rfid_code_value; - memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_with_timeout_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - timeout_in_seconds_value, - - pin_or_rfid_code_value - - ) == SL_STATUS_OK) { - return true; - } + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpointMax"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } - - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_unlock_with_timeout_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_with_timeout_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } - - return false; + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_log_record_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_max_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - uint16_t log_index_value; - memset(&log_index_value, 0x00, sizeof(log_index_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_log_record_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - log_index_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/HumidifierSetpointMax"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_log_record_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - uint16_t log_entryid_value; - memset(&log_entryid_value, 0x00, sizeof(log_entryid_value)); - uint32_t timestamp_value; - memset(×tamp_value, 0x00, sizeof(timestamp_value)); - GetLogRecordResponseEventType event_type_value; - memset(&event_type_value, 0x00, sizeof(event_type_value)); - DrlkOperEventSource source_operation_event_value; - memset(&source_operation_event_value, 0x00, sizeof(source_operation_event_value)); - uint8_t event_id_or_alarm_code_value; - memset(&event_id_or_alarm_code_value, 0x00, sizeof(event_id_or_alarm_code_value)); - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - const char* pin_value; - memset(&pin_value, 0x00, sizeof(pin_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_log_record_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - log_entryid_value, - - timestamp_value, - - event_type_value, - - source_operation_event_value, - - event_id_or_alarm_code_value, - - userid_value, - - pin_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,7,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,7,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_pin_code_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkPINUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkSettableUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - const char* pin_value; - memset(&pin_value, 0x00, sizeof(pin_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_pin_code_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_status_value, - - user_type_value, - - pin_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpoint", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpoint"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_pin_code_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkSetCodeStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_pin_code_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/HumidifierSetpoint"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_pin_code_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_publish( + const char *base_topic, + ScaleType value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkPINUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_pin_code_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + #ifdef UNIFY_HUMIDITY_CONTROL_HUMIDIFIER_SETPOINT_SCALE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_humidity_control_humidifier_setpoint_scale_get_enum_value_name((uint32_t)value); + #elif defined(SCALE_TYPE_ENUM_NAME_AVAILABLE) + jsn["value"] = scale_type_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_HUMIDIFIER_SETPOINT_SCALE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpointScale", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpointScale"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_pin_code_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_scale_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - const char* code_value; - memset(&code_value, 0x00, sizeof(code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_pin_code_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_status_value, - - user_type_value, - - code_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/HumidifierSetpointScale"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_pin_code_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_precision_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkPINUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_pin_code_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,9,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,9,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_pin_code_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_pin_code_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/HumidifierSetpointPrecision", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/HumidifierSetpointPrecision"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_all_pin_codes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_humidifier_setpoint_precision_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_pin_codes_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/HumidifierSetpointPrecision"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_all_pin_codes_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_min_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_pin_codes_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,10,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,10,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_user_status_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkSettableUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_status_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_status_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpointMin", e.what()); + return SL_STATUS_OK; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_user_status_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_status_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } - return false; + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpointMin"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_user_status_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_min_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_status_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/DehumidifierSetpointMin"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_user_status_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_max_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_status_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_status_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,11,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,11,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_weekday_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkWeekDayScheduleID scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - uint8_t days_mask_value; - memset(&days_mask_value, 0x00, sizeof(days_mask_value)); - uint8_t start_hour_value; - memset(&start_hour_value, 0x00, sizeof(start_hour_value)); - uint8_t start_minute_value; - memset(&start_minute_value, 0x00, sizeof(start_minute_value)); - uint8_t end_hour_value; - memset(&end_hour_value, 0x00, sizeof(end_hour_value)); - uint8_t end_minute_value; - memset(&end_minute_value, 0x00, sizeof(end_minute_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_weekday_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value, - - days_mask_value, - - start_hour_value, - - start_minute_value, - - end_hour_value, - - end_minute_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpointMax", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpointMax"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_weekday_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_max_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_weekday_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/DehumidifierSetpointMax"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_weekday_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkWeekDayScheduleID scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_weekday_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,12,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,12,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_weekday_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint8_t days_mask_value; - memset(&days_mask_value, 0x00, sizeof(days_mask_value)); - uint8_t start_hour_value; - memset(&start_hour_value, 0x00, sizeof(start_hour_value)); - uint8_t start_minute_value; - memset(&start_minute_value, 0x00, sizeof(start_minute_value)); - uint8_t end_hour_value; - memset(&end_hour_value, 0x00, sizeof(end_hour_value)); - uint8_t end_minute_value; - memset(&end_minute_value, 0x00, sizeof(end_minute_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_weekday_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value, - - status_value, - - days_mask_value, - - start_hour_value, - - start_minute_value, - - end_hour_value, - - end_minute_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpoint", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpoint"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_weekday_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkWeekDayScheduleID scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_weekday_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/DehumidifierSetpoint"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_weekday_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_scale_publish( + const char *base_topic, + ScaleType value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_weekday_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + #ifdef UNIFY_HUMIDITY_CONTROL_DEHUMIDIFIER_SETPOINT_SCALE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_humidity_control_dehumidifier_setpoint_scale_get_enum_value_name((uint32_t)value); + #elif defined(SCALE_TYPE_ENUM_NAME_AVAILABLE) + jsn["value"] = scale_type_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_DEHUMIDIFIER_SETPOINT_SCALE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpointScale", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpointScale"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_year_day_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_scale_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkYearDayScheduleID scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - uint32_t local_start_time_value; - memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); - uint32_t local_end_time_value; - memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_year_day_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value, - - local_start_time_value, - - local_end_time_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/DehumidifierSetpointScale"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_year_day_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precision_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_year_day_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,14,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,14,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_year_day_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkYearDayScheduleID scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_year_day_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/DehumidifierSetpointPrecision", e.what()); + return SL_STATUS_OK; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_year_day_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint32_t local_start_time_value; - memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); - uint32_t local_end_time_value; - memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_year_day_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value, - - status_value, - - local_start_time_value, - - local_end_time_value - - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_year_day_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkYearDayScheduleID scheduleid_value; - memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_year_day_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - scheduleid_value, - - userid_value - - ) == SL_STATUS_OK) { - return true; - } + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/DehumidifierSetpointPrecision"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); } - - return false; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_year_day_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_dehumidifier_setpoint_precision_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_year_day_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/DehumidifierSetpointPrecision"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_holiday_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkHolidayScheduleID holiday_scheduleid_value; - memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); - uint32_t local_start_time_value; - memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); - uint32_t local_end_time_value; - memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); - DrlkOperMode operating_mode_during_holiday_value; - memset(&operating_mode_during_holiday_value, 0x00, sizeof(operating_mode_during_holiday_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_holiday_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - holiday_scheduleid_value, - - local_start_time_value, - - local_end_time_value, - - operating_mode_during_holiday_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,15,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,15,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_holiday_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_holiday_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointMin", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointMin"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_holiday_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_min_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkHolidayScheduleID holiday_scheduleid_value; - memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_holiday_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - holiday_scheduleid_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/AutoSetpointMin"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_holiday_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - uint8_t holiday_scheduleid_value; - memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); - zclStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - uint32_t local_start_time_value; - memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); - uint32_t local_end_time_value; - memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); - DrlkOperMode operating_mode_during_holiday_value; - memset(&operating_mode_during_holiday_value, 0x00, sizeof(operating_mode_during_holiday_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_holiday_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - holiday_scheduleid_value, - - status_value, - - local_start_time_value, - - local_end_time_value, - - operating_mode_during_holiday_value - - ) == SL_STATUS_OK) { - return true; - } - } + nlohmann::json jsn; - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_holiday_schedule_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkHolidayScheduleID holiday_scheduleid_value; - memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_holiday_schedule_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - holiday_scheduleid_value - - ) == SL_STATUS_OK) { - return true; - } - } + // This is a single value - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_holiday_schedule_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_holiday_schedule_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + if (true == uic_dotdot_has_attribute_value_a_name(64928,16,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,16,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_user_type_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_type_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_type_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointMax", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointMax"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_user_type_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_max_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_type_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/AutoSetpointMax"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_user_type_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_publish( + const char *base_topic, + int32_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkTotalUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_type_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,17,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,17,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_user_type_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_type_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_type_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpoint", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpoint"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_rfid_code_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkRFIDUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkSettableUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - const char* rfid_code_value; - memset(&rfid_code_value, 0x00, sizeof(rfid_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_rfid_code_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_status_value, - - user_type_value, - - rfid_code_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/AutoSetpoint"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_set_rfid_code_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_publish( + const char *base_topic, + ScaleType value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - DrlkSetCodeStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_rfid_code_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + #ifdef UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE_ENUM_NAME_AVAILABLE + jsn["value"] = unify_humidity_control_auto_setpoint_scale_get_enum_value_name((uint32_t)value); + #elif defined(SCALE_TYPE_ENUM_NAME_AVAILABLE) + jsn["value"] = scale_type_get_enum_value_name((uint32_t)value); + #else + sl_log_warning(LOG_TAG,"Warning: Enum name not available for UNIFY_HUMIDITY_CONTROL_AUTO_SETPOINT_SCALE. Using number instead."); + jsn["value"] = static_cast(value); + #endif + + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointScale", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointScale"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_rfid_code_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_scale_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkRFIDUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_rfid_code_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/AutoSetpointScale"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_rfid_code_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_publish( + const char *base_topic, + uint8_t value, + uic_mqtt_dotdot_attribute_publish_type_t publish_type +) { - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - DrlkUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - const char* rfid_code_value; - memset(&rfid_code_value, 0x00, sizeof(rfid_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_rfid_code_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value, - - user_status_value, - - user_type_value, - - rfid_code_value - - ) == SL_STATUS_OK) { - return true; - } + nlohmann::json jsn; + + // This is a single value + + if (true == uic_dotdot_has_attribute_value_a_name(64928,19,value)) { + jsn["value"] = uic_dotdot_get_attribute_value_name(64928,19,value); + }else{ + jsn["value"] = value; } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_rfid_code_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkRFIDUserID userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_rfid_code_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - userid_value - - ) == SL_STATUS_OK) { - return true; - } + + std::string payload_str; + try { + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + payload_str = jsn.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + } catch (const nlohmann::json::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UnifyHumidityControl/Attributes/AutoSetpointPrecision", e.what()); + return SL_STATUS_OK; } - return false; + + std::string topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/AutoSetpointPrecision"; + if (publish_type & UCL_MQTT_PUBLISH_TYPE_DESIRED) + { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + if (publish_type & UCL_MQTT_PUBLISH_TYPE_REPORTED) + { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_rfid_code_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_auto_setpoint_precision_unretain( + const char *base_topic, + uic_mqtt_dotdot_attribute_publish_type_t publish_type) { - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_rfid_code_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } - } + // clang-format on + std::string topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/AutoSetpointPrecision"; - return false; + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_DESIRED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_desired = topic + "/Desired"; + uic_mqtt_publish(topic_desired.c_str(), NULL, 0, true); + } + if ((publish_type == UCL_MQTT_PUBLISH_TYPE_REPORTED) + || (publish_type == UCL_MQTT_PUBLISH_TYPE_ALL)) { + std::string topic_reported = topic + "/Reported"; + uic_mqtt_publish(topic_reported.c_str(), NULL, 0, true); + } + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) +// clang-format off + + +sl_status_t uic_mqtt_dotdot_unify_humidity_control_init() { - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + std::string base_topic = "ucl/by-unid/+/+/"; + + std::string subscription_topic; + if(!uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyHumidityControl/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_WriteAttributes); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkPassFailStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - status_value - - ) == SL_STATUS_OK) { - return true; - } + if(!uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback.empty()) { + subscription_topic = base_topic + "UnifyHumidityControl/Commands/ForceReadAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_force_read_attributes); + } + if (!uic_mqtt_dotdot_unify_humidity_control_mode_set_callback.empty()) { + subscription_topic = base_topic + "UnifyHumidityControl/Commands/ModeSet"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_mode_set); + } + if (!uic_mqtt_dotdot_unify_humidity_control_generated_mode_set_callback.empty()) { + subscription_topic = base_topic + "UnifyHumidityControl/GeneratedCommands/ModeSet"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_humidity_control_mode_set); + } + if (!uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback.empty()) { + subscription_topic = base_topic + "UnifyHumidityControl/Commands/SetpointSet"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_unify_humidity_control_setpoint_set); + } + if (!uic_mqtt_dotdot_unify_humidity_control_generated_setpoint_set_callback.empty()) { + subscription_topic = base_topic + "UnifyHumidityControl/GeneratedCommands/SetpointSet"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_generated_unify_humidity_control_setpoint_set); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_user_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DataOperationTypeEnum operation_type_value; - memset(&operation_type_value, 0x00, sizeof(operation_type_value)); - uint16_t user_index_value; - memset(&user_index_value, 0x00, sizeof(user_index_value)); - const char* user_name_value; - memset(&user_name_value, 0x00, sizeof(user_name_value)); - uint32_t user_uniqueid_value; - memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); - DrlkSettableUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - CredentialRuleEnum credential_rule_value; - memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - operation_type_value, - - user_index_value, - - user_name_value, - - user_uniqueid_value, - - user_status_value, - - user_type_value, - - credential_rule_value - - ) == SL_STATUS_OK) { - return true; - } - } + // Init the attributes for that cluster + uic_mqtt_dotdot_unify_humidity_control_attributes_init(); - return false; + uic_mqtt_dotdot_by_group_unify_humidity_control_init(); + + return SL_STATUS_OK; } -static inline bool uic_mqtt_dotdot_door_lock_get_user_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t user_index_value; - memset(&user_index_value, 0x00, sizeof(user_index_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - user_index_value - - ) == SL_STATUS_OK) { - return true; - } + + +sl_status_t uic_mqtt_dotdot_init() { + + sl_status_t status_flag = SL_STATUS_OK; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_basic_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_user_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_power_configuration_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_user_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t user_index_value; - memset(&user_index_value, 0x00, sizeof(user_index_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_user_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - user_index_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_device_temperature_configuration_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_operating_event_notification_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DrlkOperEventSource operation_event_source_value; - memset(&operation_event_source_value, 0x00, sizeof(operation_event_source_value)); - OperatingEventNotificationOperationEventCode operation_event_code_value; - memset(&operation_event_code_value, 0x00, sizeof(operation_event_code_value)); - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - const char* pin_value; - memset(&pin_value, 0x00, sizeof(pin_value)); - uint32_t local_time_value; - memset(&local_time_value, 0x00, sizeof(local_time_value)); - const char* data_value; - memset(&data_value, 0x00, sizeof(data_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_operating_event_notification_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - operation_event_source_value, - - operation_event_code_value, - - userid_value, - - pin_value, - - local_time_value, - - data_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_identify_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_programming_event_notification_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - ProgrammingEventNotificationProgramEventSource program_event_source_value; - memset(&program_event_source_value, 0x00, sizeof(program_event_source_value)); - ProgrammingEventNotificationProgramEventCode program_event_code_value; - memset(&program_event_code_value, 0x00, sizeof(program_event_code_value)); - uint16_t userid_value; - memset(&userid_value, 0x00, sizeof(userid_value)); - const char* pin_value; - memset(&pin_value, 0x00, sizeof(pin_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - DrlkUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - uint32_t local_time_value; - memset(&local_time_value, 0x00, sizeof(local_time_value)); - const char* data_value; - memset(&data_value, 0x00, sizeof(data_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_programming_event_notification_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - program_event_source_value, - - program_event_code_value, - - userid_value, - - pin_value, - - user_type_value, - - user_status_value, - - local_time_value, - - data_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_groups_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_credential_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - DataOperationTypeEnum operation_type_value; - memset(&operation_type_value, 0x00, sizeof(operation_type_value)); - CredentialStruct credential_value; - memset(&credential_value, 0x00, sizeof(credential_value)); - const char* credential_data_value; - memset(&credential_data_value, 0x00, sizeof(credential_data_value)); - uint16_t user_index_value; - memset(&user_index_value, 0x00, sizeof(user_index_value)); - DrlkSettableUserStatus user_status_value; - memset(&user_status_value, 0x00, sizeof(user_status_value)); - DrlkUserType user_type_value; - memset(&user_type_value, 0x00, sizeof(user_type_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_credential_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - operation_type_value, - - credential_value, - - credential_data_value, - - user_index_value, - - user_status_value, - - user_type_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_scenes_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_set_credential_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_door_lock_set_credential_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_on_off_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_credential_status_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - CredentialStruct credential_value; - memset(&credential_value, 0x00, sizeof(credential_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_credential_status_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - credential_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_level_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_get_credential_status_response_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_door_lock_get_credential_status_response_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_alarms_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_clear_credential_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - CredentialStruct credential_value; - memset(&credential_value, 0x00, sizeof(credential_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_credential_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - credential_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_time_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_unbolt_door_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* pin_code_value; - memset(&pin_code_value, 0x00, sizeof(pin_code_value)); - for (const auto& callback: uic_mqtt_dotdot_door_lock_unbolt_door_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - pin_code_value - - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_poll_control_init(); } - return false; -} + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_shade_configuration_init(); + } -static inline bool uic_mqtt_dotdot_door_lock_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_door_lock_write_attributes_callback) { - uic_mqtt_dotdot_door_lock_state_t door_lock_new_state = {}; - uic_mqtt_dotdot_door_lock_updated_state_t door_lock_new_updated_state = {}; + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_door_lock_init(); + } - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - door_lock_new_state, - door_lock_new_updated_state - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_window_covering_init(); } - return false; -} -static inline bool uic_mqtt_dotdot_door_lock_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_door_lock_force_read_attributes_callback) { - uic_mqtt_dotdot_door_lock_updated_state_t door_lock_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - door_lock_force_update - ) == SL_STATUS_OK) { - return true; - } + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_barrier_control_init(); } - return false; -} -// Publishing Supported Commands for DoorLock Cluster -void uic_mqtt_dotdot_door_lock_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_pump_configuration_and_control_init(); + } - // check if there is callback for each command - if (uic_mqtt_dotdot_door_lock_lock_door_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("LockDoor")"; + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_thermostat_init(); } - if (uic_mqtt_dotdot_door_lock_lock_door_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("LockDoorResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_fan_control_init(); } - if (uic_mqtt_dotdot_door_lock_unlock_door_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("UnlockDoor")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_dehumidification_control_init(); } - if (uic_mqtt_dotdot_door_lock_unlock_door_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("UnlockDoorResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_thermostat_user_interface_configuration_init(); } - if (uic_mqtt_dotdot_door_lock_toggle_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Toggle")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_color_control_init(); } - if (uic_mqtt_dotdot_door_lock_toggle_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ToggleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_ballast_configuration_init(); } - if (uic_mqtt_dotdot_door_lock_unlock_with_timeout_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("UnlockWithTimeout")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_illuminance_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_unlock_with_timeout_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("UnlockWithTimeoutResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_illuminance_level_sensing_init(); } - if (uic_mqtt_dotdot_door_lock_get_log_record_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetLogRecord")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_temperature_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_get_log_record_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetLogRecordResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_pressure_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_set_pin_code_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetPINCode")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_flow_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_set_pin_code_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetPINCodeResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_relativity_humidity_init(); } - if (uic_mqtt_dotdot_door_lock_get_pin_code_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetPINCode")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_occupancy_sensing_init(); } - if (uic_mqtt_dotdot_door_lock_get_pin_code_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetPINCodeResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_soil_moisture_init(); } - if (uic_mqtt_dotdot_door_lock_clear_pin_code_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearPINCode")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_ph_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_clear_pin_code_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearPINCodeResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_electrical_conductivity_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_clear_all_pin_codes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearAllPINCodes")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_wind_speed_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_clear_all_pin_codes_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearAllPINCodesResponse")"; - } - if (uic_mqtt_dotdot_door_lock_set_user_status_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetUserStatus")"; - } - if (uic_mqtt_dotdot_door_lock_set_user_status_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetUserStatusResponse")"; - } - if (uic_mqtt_dotdot_door_lock_get_user_status_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetUserStatus")"; - } - if (uic_mqtt_dotdot_door_lock_get_user_status_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetUserStatusResponse")"; - } - if (uic_mqtt_dotdot_door_lock_set_weekday_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetWeekdaySchedule")"; - } - if (uic_mqtt_dotdot_door_lock_set_weekday_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetWeekdayScheduleResponse")"; - } - if (uic_mqtt_dotdot_door_lock_get_weekday_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetWeekdaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_carbon_monoxide_init(); } - if (uic_mqtt_dotdot_door_lock_get_weekday_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetWeekdayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_carbon_dioxide_init(); } - if (uic_mqtt_dotdot_door_lock_clear_weekday_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearWeekdaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_pm25_init(); } - if (uic_mqtt_dotdot_door_lock_clear_weekday_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearWeekdayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_ias_zone_init(); } - if (uic_mqtt_dotdot_door_lock_set_year_day_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetYearDaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_iaswd_init(); } - if (uic_mqtt_dotdot_door_lock_set_year_day_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetYearDayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_metering_init(); } - if (uic_mqtt_dotdot_door_lock_get_year_day_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetYearDaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_electrical_measurement_init(); } - if (uic_mqtt_dotdot_door_lock_get_year_day_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetYearDayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_diagnostics_init(); } - if (uic_mqtt_dotdot_door_lock_clear_year_day_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearYearDaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_protocol_controller_rf_telemetry_init(); } - if (uic_mqtt_dotdot_door_lock_clear_year_day_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearYearDayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_state_init(); } - if (uic_mqtt_dotdot_door_lock_set_holiday_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetHolidaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_binding_init(); } - if (uic_mqtt_dotdot_door_lock_set_holiday_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetHolidayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_system_metrics_init(); } - if (uic_mqtt_dotdot_door_lock_get_holiday_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetHolidaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_application_monitoring_init(); } - if (uic_mqtt_dotdot_door_lock_get_holiday_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetHolidayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_name_and_location_init(); } - if (uic_mqtt_dotdot_door_lock_clear_holiday_schedule_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearHolidaySchedule")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_configuration_parameters_init(); } - if (uic_mqtt_dotdot_door_lock_clear_holiday_schedule_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearHolidayScheduleResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_user_credential_init(); } - if (uic_mqtt_dotdot_door_lock_set_user_type_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetUserType")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_aox_locator_init(); } - if (uic_mqtt_dotdot_door_lock_set_user_type_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetUserTypeResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_aox_position_estimation_init(); } - if (uic_mqtt_dotdot_door_lock_get_user_type_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetUserType")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_protocol_controller_network_management_init(); } - if (uic_mqtt_dotdot_door_lock_get_user_type_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetUserTypeResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_descriptor_init(); } - if (uic_mqtt_dotdot_door_lock_set_rfid_code_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetRFIDCode")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_unify_fan_control_init(); } - if (uic_mqtt_dotdot_door_lock_set_rfid_code_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetRFIDCodeResponse")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_unify_thermostat_init(); } - if (uic_mqtt_dotdot_door_lock_get_rfid_code_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetRFIDCode")"; + + if (status_flag == SL_STATUS_OK) { + status_flag = uic_mqtt_dotdot_unify_humidity_control_init(); } - if (uic_mqtt_dotdot_door_lock_get_rfid_code_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + + + return status_flag; +} + +// Publish all supported dotdot cluster commands per each endpoints. +void uic_mqtt_dotdot_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uic_mqtt_dotdot_basic_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_power_configuration_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_device_temperature_configuration_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_identify_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_groups_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_scenes_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_on_off_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_level_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_alarms_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_time_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_poll_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_shade_configuration_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_door_lock_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_window_covering_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_barrier_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_thermostat_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_fan_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_dehumidification_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_color_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_ballast_configuration_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_illuminance_level_sensing_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_temperature_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_pressure_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_flow_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_relativity_humidity_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_soil_moisture_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_ph_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_electrical_conductivity_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_wind_speed_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_carbon_monoxide_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_carbon_dioxide_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_pm25_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_ias_zone_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_iaswd_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_metering_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_electrical_measurement_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_diagnostics_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_supported_commands(unid, 0); + uic_mqtt_dotdot_state_publish_supported_commands(unid, 0); + uic_mqtt_dotdot_binding_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_system_metrics_publish_supported_commands(unid, 0); + uic_mqtt_dotdot_application_monitoring_publish_supported_commands(unid, 0); + uic_mqtt_dotdot_name_and_location_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_configuration_parameters_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_user_credential_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_aox_locator_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_commands(unid, 0); + uic_mqtt_dotdot_descriptor_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_fan_control_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_thermostat_publish_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_humidity_control_publish_supported_commands(unid, endpoint_id); +} + +void uic_mqtt_dotdot_publish_empty_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uic_mqtt_dotdot_basic_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_power_configuration_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_device_temperature_configuration_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_identify_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_groups_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_scenes_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_on_off_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_level_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_alarms_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_time_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_poll_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_shade_configuration_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_door_lock_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_window_covering_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_barrier_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_pump_configuration_and_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_thermostat_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_fan_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_dehumidification_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_color_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_ballast_configuration_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_illuminance_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_illuminance_level_sensing_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_temperature_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_pressure_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_flow_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_relativity_humidity_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_occupancy_sensing_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_soil_moisture_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_ph_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_electrical_conductivity_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_wind_speed_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_carbon_monoxide_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_carbon_dioxide_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_pm25_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_ias_zone_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_iaswd_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_metering_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_electrical_measurement_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_diagnostics_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_empty_supported_commands(unid); + uic_mqtt_dotdot_state_publish_empty_supported_commands(unid); + uic_mqtt_dotdot_binding_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_system_metrics_publish_empty_supported_commands(unid); + uic_mqtt_dotdot_application_monitoring_publish_empty_supported_commands(unid); + uic_mqtt_dotdot_name_and_location_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_configuration_parameters_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_user_credential_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_aox_locator_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_aox_position_estimation_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_protocol_controller_network_management_publish_empty_supported_commands(unid); + uic_mqtt_dotdot_descriptor_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_fan_control_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands(unid, endpoint_id); + uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands(unid, endpoint_id); +} + +// Publishing Cluster Revision for Basic Cluster +void uic_mqtt_dotdot_basic_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/Basic/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for Basic Cluster +void uic_mqtt_dotdot_basic_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/Basic/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_basic_reset_to_factory_defaults_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_basic_reset_to_factory_defaults_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("GetRFIDCodeResponse")"; } - if (uic_mqtt_dotdot_door_lock_clear_rfid_code_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + + return false; +} + +static inline bool uic_mqtt_dotdot_basic_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_basic_write_attributes_callback) { + uic_mqtt_dotdot_basic_state_t basic_new_state = {}; + uic_mqtt_dotdot_basic_updated_state_t basic_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + basic_new_state, + basic_new_updated_state + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ClearRFIDCode")"; } - if (uic_mqtt_dotdot_door_lock_clear_rfid_code_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} + +static inline bool uic_mqtt_dotdot_basic_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_basic_force_read_attributes_callback) { + uic_mqtt_dotdot_basic_updated_state_t basic_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + basic_force_update + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ClearRFIDCodeResponse")"; } - if (uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_is_supported(unid, endpoint_id)) { + return false; +} + +// Publishing Supported Commands for Basic Cluster +void uic_mqtt_dotdot_basic_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_basic_reset_to_factory_defaults_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ClearAllRFIDCodes")"; + ss << R"("ResetToFactoryDefaults")"; } - if (uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_response_is_supported(unid, endpoint_id)) { + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_basic_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ClearAllRFIDCodesResponse")"; + ss << R"("WriteAttributes")"; } - if (uic_mqtt_dotdot_door_lock_set_user_is_supported(unid, endpoint_id)) { + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_basic_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("SetUser")"; - } - if (uic_mqtt_dotdot_door_lock_get_user_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetUser")"; - } - if (uic_mqtt_dotdot_door_lock_get_user_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetUserResponse")"; - } - if (uic_mqtt_dotdot_door_lock_clear_user_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearUser")"; - } - if (uic_mqtt_dotdot_door_lock_operating_event_notification_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("OperatingEventNotification")"; - } - if (uic_mqtt_dotdot_door_lock_programming_event_notification_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ProgrammingEventNotification")"; - } - if (uic_mqtt_dotdot_door_lock_set_credential_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetCredential")"; - } - if (uic_mqtt_dotdot_door_lock_set_credential_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetCredentialResponse")"; - } - if (uic_mqtt_dotdot_door_lock_get_credential_status_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetCredentialStatus")"; - } - if (uic_mqtt_dotdot_door_lock_get_credential_status_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GetCredentialStatusResponse")"; - } - if (uic_mqtt_dotdot_door_lock_clear_credential_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ClearCredential")"; - } - if (uic_mqtt_dotdot_door_lock_unbolt_door_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("UnboltDoor")"; - } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_door_lock_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_door_lock_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("ForceReadAttributes")"; } // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/DoorLock/SupportedCommands"; + topic += "/Basic/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -103687,7 +102511,7 @@ void uic_mqtt_dotdot_door_lock_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/DoorLock/Attributes"; + attributes_topic += "/Basic/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -103698,14 +102522,14 @@ void uic_mqtt_dotdot_door_lock_publish_supported_commands( } } -// Publishing empty/no Supported Commands for DoorLock Cluster -void uic_mqtt_dotdot_door_lock_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Basic Cluster +void uic_mqtt_dotdot_basic_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/DoorLock/SupportedCommands"; + topic += "/Basic/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -103715,10 +102539,10 @@ void uic_mqtt_dotdot_door_lock_publish_empty_supported_commands( } } -// Publishing Cluster Revision for WindowCovering Cluster -void uic_mqtt_dotdot_window_covering_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for PowerConfiguration Cluster +void uic_mqtt_dotdot_power_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/WindowCovering/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/PowerConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -103735,13 +102559,13 @@ void uic_mqtt_dotdot_window_covering_publish_cluster_revision(const char* base_t true); } -// Unretain Cluster Revision for WindowCovering Cluster -void uic_mqtt_dotdot_window_covering_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for PowerConfiguration Cluster +void uic_mqtt_dotdot_power_configuration_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/WindowCovering/Attributes/ClusterRevision"; + + "/PowerConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -103751,135 +102575,21 @@ void uic_mqtt_dotdot_window_covering_unretain_cluster_revision(const char* base_ // clang-format off } -static inline bool uic_mqtt_dotdot_window_covering_up_or_open_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_window_covering_up_or_open_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_down_or_close_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_window_covering_down_or_close_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_stop_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_window_covering_stop_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_go_to_lift_value_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t lift_value_value; - memset(&lift_value_value, 0x00, sizeof(lift_value_value)); - for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_lift_value_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - lift_value_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_go_to_lift_percentage_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t percentage_lift_value_value; - memset(&percentage_lift_value_value, 0x00, sizeof(percentage_lift_value_value)); - for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_lift_percentage_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - percentage_lift_value_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_go_to_tilt_value_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t tilt_value_value; - memset(&tilt_value_value, 0x00, sizeof(tilt_value_value)); - for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_tilt_value_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - tilt_value_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_go_to_tilt_percentage_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t percentage_tilt_value_value; - memset(&percentage_tilt_value_value, 0x00, sizeof(percentage_tilt_value_value)); - for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_tilt_percentage_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - percentage_tilt_value_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_window_covering_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_power_configuration_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_window_covering_write_attributes_callback) { - uic_mqtt_dotdot_window_covering_state_t window_covering_new_state = {}; - uic_mqtt_dotdot_window_covering_updated_state_t window_covering_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_power_configuration_write_attributes_callback) { + uic_mqtt_dotdot_power_configuration_state_t power_configuration_new_state = {}; + uic_mqtt_dotdot_power_configuration_updated_state_t power_configuration_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - window_covering_new_state, - window_covering_new_updated_state + power_configuration_new_state, + power_configuration_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -103887,17 +102597,17 @@ static inline bool uic_mqtt_dotdot_window_covering_write_attributes_is_supported return false; } -static inline bool uic_mqtt_dotdot_window_covering_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_power_configuration_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_window_covering_force_read_attributes_callback) { - uic_mqtt_dotdot_window_covering_updated_state_t window_covering_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_power_configuration_force_read_attributes_callback) { + uic_mqtt_dotdot_power_configuration_updated_state_t power_configuration_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - window_covering_force_update + power_configuration_force_update ) == SL_STATUS_OK) { return true; } @@ -103905,8 +102615,8 @@ static inline bool uic_mqtt_dotdot_window_covering_force_read_attributes_is_supp return false; } -// Publishing Supported Commands for WindowCovering Cluster -void uic_mqtt_dotdot_window_covering_publish_supported_commands( +// Publishing Supported Commands for PowerConfiguration Cluster +void uic_mqtt_dotdot_power_configuration_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -103915,67 +102625,18 @@ void uic_mqtt_dotdot_window_covering_publish_supported_commands( ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_window_covering_up_or_open_is_supported(unid, endpoint_id)) { + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_power_configuration_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("UpOrOpen")"; - } - if (uic_mqtt_dotdot_window_covering_down_or_close_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("DownOrClose")"; - } - if (uic_mqtt_dotdot_window_covering_stop_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Stop")"; - } - if (uic_mqtt_dotdot_window_covering_go_to_lift_value_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GoToLiftValue")"; - } - if (uic_mqtt_dotdot_window_covering_go_to_lift_percentage_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GoToLiftPercentage")"; - } - if (uic_mqtt_dotdot_window_covering_go_to_tilt_value_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GoToTiltValue")"; - } - if (uic_mqtt_dotdot_window_covering_go_to_tilt_percentage_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GoToTiltPercentage")"; - } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_window_covering_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("WriteAttributes")"; } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_window_covering_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_power_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -103986,7 +102647,7 @@ void uic_mqtt_dotdot_window_covering_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/WindowCovering/SupportedCommands"; + topic += "/PowerConfiguration/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -103998,7 +102659,7 @@ void uic_mqtt_dotdot_window_covering_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/WindowCovering/Attributes"; + attributes_topic += "/PowerConfiguration/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104009,14 +102670,14 @@ void uic_mqtt_dotdot_window_covering_publish_supported_commands( } } -// Publishing empty/no Supported Commands for WindowCovering Cluster -void uic_mqtt_dotdot_window_covering_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for PowerConfiguration Cluster +void uic_mqtt_dotdot_power_configuration_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/WindowCovering/SupportedCommands"; + topic += "/PowerConfiguration/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104026,10 +102687,10 @@ void uic_mqtt_dotdot_window_covering_publish_empty_supported_commands( } } -// Publishing Cluster Revision for BarrierControl Cluster -void uic_mqtt_dotdot_barrier_control_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for DeviceTemperatureConfiguration Cluster +void uic_mqtt_dotdot_device_temperature_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/BarrierControl/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/DeviceTemperatureConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -104046,13 +102707,13 @@ void uic_mqtt_dotdot_barrier_control_publish_cluster_revision(const char* base_t true); } -// Unretain Cluster Revision for BarrierControl Cluster -void uic_mqtt_dotdot_barrier_control_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for DeviceTemperatureConfiguration Cluster +void uic_mqtt_dotdot_device_temperature_configuration_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/BarrierControl/Attributes/ClusterRevision"; + + "/DeviceTemperatureConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -104062,53 +102723,21 @@ void uic_mqtt_dotdot_barrier_control_unretain_cluster_revision(const char* base_ // clang-format off } -static inline bool uic_mqtt_dotdot_barrier_control_go_to_percent_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t percent_open_value; - memset(&percent_open_value, 0x00, sizeof(percent_open_value)); - for (const auto& callback: uic_mqtt_dotdot_barrier_control_go_to_percent_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - percent_open_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_barrier_control_stop_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_barrier_control_stop_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_barrier_control_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_device_temperature_configuration_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_barrier_control_write_attributes_callback) { - uic_mqtt_dotdot_barrier_control_state_t barrier_control_new_state = {}; - uic_mqtt_dotdot_barrier_control_updated_state_t barrier_control_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_device_temperature_configuration_write_attributes_callback) { + uic_mqtt_dotdot_device_temperature_configuration_state_t device_temperature_configuration_new_state = {}; + uic_mqtt_dotdot_device_temperature_configuration_updated_state_t device_temperature_configuration_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - barrier_control_new_state, - barrier_control_new_updated_state + device_temperature_configuration_new_state, + device_temperature_configuration_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -104116,17 +102745,17 @@ static inline bool uic_mqtt_dotdot_barrier_control_write_attributes_is_supported return false; } -static inline bool uic_mqtt_dotdot_barrier_control_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_device_temperature_configuration_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_barrier_control_force_read_attributes_callback) { - uic_mqtt_dotdot_barrier_control_updated_state_t barrier_control_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_device_temperature_configuration_force_read_attributes_callback) { + uic_mqtt_dotdot_device_temperature_configuration_updated_state_t device_temperature_configuration_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - barrier_control_force_update + device_temperature_configuration_force_update ) == SL_STATUS_OK) { return true; } @@ -104134,8 +102763,8 @@ static inline bool uic_mqtt_dotdot_barrier_control_force_read_attributes_is_supp return false; } -// Publishing Supported Commands for BarrierControl Cluster -void uic_mqtt_dotdot_barrier_control_publish_supported_commands( +// Publishing Supported Commands for DeviceTemperatureConfiguration Cluster +void uic_mqtt_dotdot_device_temperature_configuration_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -104144,23 +102773,9 @@ void uic_mqtt_dotdot_barrier_control_publish_supported_commands( ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_barrier_control_go_to_percent_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("GoToPercent")"; - } - if (uic_mqtt_dotdot_barrier_control_stop_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Stop")"; - } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_barrier_control_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_device_temperature_configuration_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -104169,7 +102784,7 @@ void uic_mqtt_dotdot_barrier_control_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_barrier_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_device_temperature_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -104180,7 +102795,7 @@ void uic_mqtt_dotdot_barrier_control_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/BarrierControl/SupportedCommands"; + topic += "/DeviceTemperatureConfiguration/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -104192,7 +102807,7 @@ void uic_mqtt_dotdot_barrier_control_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/BarrierControl/Attributes"; + attributes_topic += "/DeviceTemperatureConfiguration/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104203,14 +102818,14 @@ void uic_mqtt_dotdot_barrier_control_publish_supported_commands( } } -// Publishing empty/no Supported Commands for BarrierControl Cluster -void uic_mqtt_dotdot_barrier_control_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for DeviceTemperatureConfiguration Cluster +void uic_mqtt_dotdot_device_temperature_configuration_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/BarrierControl/SupportedCommands"; + topic += "/DeviceTemperatureConfiguration/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104220,10 +102835,10 @@ void uic_mqtt_dotdot_barrier_control_publish_empty_supported_commands( } } -// Publishing Cluster Revision for PumpConfigurationAndControl Cluster -void uic_mqtt_dotdot_pump_configuration_and_control_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Identify Cluster +void uic_mqtt_dotdot_identify_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/PumpConfigurationAndControl/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Identify/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -104240,13 +102855,13 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_cluster_revision(con true); } -// Unretain Cluster Revision for PumpConfigurationAndControl Cluster -void uic_mqtt_dotdot_pump_configuration_and_control_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Identify Cluster +void uic_mqtt_dotdot_identify_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/PumpConfigurationAndControl/Attributes/ClusterRevision"; + + "/Identify/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -104256,39 +102871,93 @@ void uic_mqtt_dotdot_pump_configuration_and_control_unretain_cluster_revision(co // clang-format off } +static inline bool uic_mqtt_dotdot_identify_identify_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t identify_time_value; + memset(&identify_time_value, 0x00, sizeof(identify_time_value)); + for (const auto& callback: uic_mqtt_dotdot_identify_identify_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + identify_time_value + + ) == SL_STATUS_OK) { + return true; + } + } -static inline bool uic_mqtt_dotdot_pump_configuration_and_control_write_attributes_is_supported( + return false; +} +static inline bool uic_mqtt_dotdot_identify_identify_query_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_pump_configuration_and_control_write_attributes_callback) { - uic_mqtt_dotdot_pump_configuration_and_control_state_t pump_configuration_and_control_new_state = {}; - uic_mqtt_dotdot_pump_configuration_and_control_updated_state_t pump_configuration_and_control_new_updated_state = {}; + uint16_t timeout_value; + memset(&timeout_value, 0x00, sizeof(timeout_value)); + for (const auto& callback: uic_mqtt_dotdot_identify_identify_query_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + timeout_value + + ) == SL_STATUS_OK) { + return true; + } + } - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - pump_configuration_and_control_new_state, - pump_configuration_and_control_new_updated_state - ) == SL_STATUS_OK) { + return false; +} +static inline bool uic_mqtt_dotdot_identify_identify_query_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_identify_identify_query_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_identify_trigger_effect_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + TriggerEffectEffectIdentifier effect_identifier_value; + memset(&effect_identifier_value, 0x00, sizeof(effect_identifier_value)); + TriggerEffectEffectVariant effect_variant_value; + memset(&effect_variant_value, 0x00, sizeof(effect_variant_value)); + for (const auto& callback: uic_mqtt_dotdot_identify_trigger_effect_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + effect_identifier_value, + + effect_variant_value + + ) == SL_STATUS_OK) { return true; } } + return false; } -static inline bool uic_mqtt_dotdot_pump_configuration_and_control_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_identify_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_pump_configuration_and_control_force_read_attributes_callback) { - uic_mqtt_dotdot_pump_configuration_and_control_updated_state_t pump_configuration_and_control_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_identify_write_attributes_callback) { + uic_mqtt_dotdot_identify_state_t identify_new_state = {}; + uic_mqtt_dotdot_identify_updated_state_t identify_new_updated_state = {}; + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - pump_configuration_and_control_force_update + identify_new_state, + identify_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -104296,8 +102965,26 @@ static inline bool uic_mqtt_dotdot_pump_configuration_and_control_force_read_att return false; } -// Publishing Supported Commands for PumpConfigurationAndControl Cluster -void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( +static inline bool uic_mqtt_dotdot_identify_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_identify_force_read_attributes_callback) { + uic_mqtt_dotdot_identify_updated_state_t identify_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + identify_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Identify Cluster +void uic_mqtt_dotdot_identify_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -104306,9 +102993,37 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( ss.str(""); // check if there is callback for each command + if (uic_mqtt_dotdot_identify_identify_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Identify")"; + } + if (uic_mqtt_dotdot_identify_identify_query_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("IdentifyQueryResponse")"; + } + if (uic_mqtt_dotdot_identify_identify_query_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("IdentifyQuery")"; + } + if (uic_mqtt_dotdot_identify_trigger_effect_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("TriggerEffect")"; + } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_pump_configuration_and_control_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_identify_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -104317,7 +103032,7 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_pump_configuration_and_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_identify_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -104328,7 +103043,7 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PumpConfigurationAndControl/SupportedCommands"; + topic += "/Identify/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -104340,7 +103055,7 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/PumpConfigurationAndControl/Attributes"; + attributes_topic += "/Identify/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104351,14 +103066,14 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( } } -// Publishing empty/no Supported Commands for PumpConfigurationAndControl Cluster -void uic_mqtt_dotdot_pump_configuration_and_control_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Identify Cluster +void uic_mqtt_dotdot_identify_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PumpConfigurationAndControl/SupportedCommands"; + topic += "/Identify/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104368,10 +103083,10 @@ void uic_mqtt_dotdot_pump_configuration_and_control_publish_empty_supported_comm } } -// Publishing Cluster Revision for Thermostat Cluster -void uic_mqtt_dotdot_thermostat_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Groups Cluster +void uic_mqtt_dotdot_groups_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/Thermostat/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Groups/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -104388,13 +103103,13 @@ void uic_mqtt_dotdot_thermostat_publish_cluster_revision(const char* base_topic, true); } -// Unretain Cluster Revision for Thermostat Cluster -void uic_mqtt_dotdot_thermostat_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Groups Cluster +void uic_mqtt_dotdot_groups_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/Thermostat/Attributes/ClusterRevision"; + + "/Groups/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -104404,20 +103119,20 @@ void uic_mqtt_dotdot_thermostat_unretain_cluster_revision(const char* base_topic // clang-format off } -static inline bool uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_is_supported( +static inline bool uic_mqtt_dotdot_groups_add_group_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - SetpointRaiseOrLowerMode mode_value; - memset(&mode_value, 0x00, sizeof(mode_value)); - int8_t amount_value; - memset(&amount_value, 0x00, sizeof(amount_value)); - for (const auto& callback: uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_callback) { + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + const char* group_name_value; + memset(&group_name_value, 0x00, sizeof(group_name_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_add_group_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - mode_value, + group_id_value, - amount_value + group_name_value ) == SL_STATUS_OK) { return true; @@ -104426,27 +103141,21 @@ static inline bool uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_is_support return false; } -static inline bool uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_is_supported( +static inline bool uic_mqtt_dotdot_groups_add_group_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t number_of_transitions_value; - memset(&number_of_transitions_value, 0x00, sizeof(number_of_transitions_value)); - uint8_t day_of_week_value; - memset(&day_of_week_value, 0x00, sizeof(day_of_week_value)); - uint8_t mode_value; - memset(&mode_value, 0x00, sizeof(mode_value)); - for (const auto& callback: uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_callback) { + uint8_t status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_add_group_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - number_of_transitions_value, - - day_of_week_value, + status_value, - mode_value, + group_id_value - 0, nullptr - ) == SL_STATUS_OK) { return true; } @@ -104454,27 +103163,17 @@ static inline bool uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_is_su return false; } -static inline bool uic_mqtt_dotdot_thermostat_set_weekly_schedule_is_supported( +static inline bool uic_mqtt_dotdot_groups_view_group_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t number_of_transitions_value; - memset(&number_of_transitions_value, 0x00, sizeof(number_of_transitions_value)); - uint8_t day_of_week_value; - memset(&day_of_week_value, 0x00, sizeof(day_of_week_value)); - uint8_t mode_value; - memset(&mode_value, 0x00, sizeof(mode_value)); - for (const auto& callback: uic_mqtt_dotdot_thermostat_set_weekly_schedule_callback) { + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_view_group_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - number_of_transitions_value, - - day_of_week_value, - - mode_value, + group_id_value - 0, nullptr - ) == SL_STATUS_OK) { return true; } @@ -104482,36 +103181,24 @@ static inline bool uic_mqtt_dotdot_thermostat_set_weekly_schedule_is_supported( return false; } -static inline bool uic_mqtt_dotdot_thermostat_get_relay_status_log_response_is_supported( +static inline bool uic_mqtt_dotdot_groups_view_group_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t time_of_day_value; - memset(&time_of_day_value, 0x00, sizeof(time_of_day_value)); - uint8_t relay_status_value; - memset(&relay_status_value, 0x00, sizeof(relay_status_value)); - int16_t local_temperature_value; - memset(&local_temperature_value, 0x00, sizeof(local_temperature_value)); - uint8_t humidity_percentage_value; - memset(&humidity_percentage_value, 0x00, sizeof(humidity_percentage_value)); - int16_t set_point_value; - memset(&set_point_value, 0x00, sizeof(set_point_value)); - uint16_t unread_entries_value; - memset(&unread_entries_value, 0x00, sizeof(unread_entries_value)); - for (const auto& callback: uic_mqtt_dotdot_thermostat_get_relay_status_log_response_callback) { + uint8_t status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + const char* group_name_value; + memset(&group_name_value, 0x00, sizeof(group_name_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_view_group_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - time_of_day_value, - - relay_status_value, - - local_temperature_value, - - humidity_percentage_value, + status_value, - set_point_value, + group_id_value, - unread_entries_value + group_name_value ) == SL_STATUS_OK) { return true; @@ -104520,21 +103207,15 @@ static inline bool uic_mqtt_dotdot_thermostat_get_relay_status_log_response_is_s return false; } -static inline bool uic_mqtt_dotdot_thermostat_get_weekly_schedule_is_supported( +static inline bool uic_mqtt_dotdot_groups_get_group_membership_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t days_to_return_value; - memset(&days_to_return_value, 0x00, sizeof(days_to_return_value)); - uint8_t mode_to_return_value; - memset(&mode_to_return_value, 0x00, sizeof(mode_to_return_value)); - for (const auto& callback: uic_mqtt_dotdot_thermostat_get_weekly_schedule_callback) { + for (const auto& callback: uic_mqtt_dotdot_groups_get_group_membership_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - days_to_return_value, - - mode_to_return_value - + 0, nullptr + ) == SL_STATUS_OK) { return true; } @@ -104542,13 +103223,19 @@ static inline bool uic_mqtt_dotdot_thermostat_get_weekly_schedule_is_supported( return false; } -static inline bool uic_mqtt_dotdot_thermostat_clear_weekly_schedule_is_supported( +static inline bool uic_mqtt_dotdot_groups_get_group_membership_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_thermostat_clear_weekly_schedule_callback) { + uint8_t capacity_value; + memset(&capacity_value, 0x00, sizeof(capacity_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_get_group_membership_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + capacity_value, + 0, nullptr + ) == SL_STATUS_OK) { return true; } @@ -104556,12 +103243,16 @@ static inline bool uic_mqtt_dotdot_thermostat_clear_weekly_schedule_is_supported return false; } -static inline bool uic_mqtt_dotdot_thermostat_get_relay_status_log_is_supported( +static inline bool uic_mqtt_dotdot_groups_remove_group_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_thermostat_get_relay_status_log_callback) { + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_remove_group_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + group_id_value ) == SL_STATUS_OK) { return true; @@ -104570,108 +103261,187 @@ static inline bool uic_mqtt_dotdot_thermostat_get_relay_status_log_is_supported( return false; } - -static inline bool uic_mqtt_dotdot_thermostat_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_groups_remove_group_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_thermostat_write_attributes_callback) { - uic_mqtt_dotdot_thermostat_state_t thermostat_new_state = {}; - uic_mqtt_dotdot_thermostat_updated_state_t thermostat_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - thermostat_new_state, - thermostat_new_updated_state - ) == SL_STATUS_OK) { + uint8_t status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_remove_group_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + group_id_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_thermostat_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_groups_remove_all_groups_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_thermostat_force_read_attributes_callback) { - uic_mqtt_dotdot_thermostat_updated_state_t thermostat_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - thermostat_force_update - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_groups_remove_all_groups_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for Thermostat Cluster -void uic_mqtt_dotdot_thermostat_publish_supported_commands( +static inline bool uic_mqtt_dotdot_groups_add_group_if_identifying_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetpointRaiseOrLower")"; + uint16_t group_id_value; + memset(&group_id_value, 0x00, sizeof(group_id_value)); + const char* group_name_value; + memset(&group_name_value, 0x00, sizeof(group_name_value)); + for (const auto& callback: uic_mqtt_dotdot_groups_add_group_if_identifying_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + group_id_value, + + group_name_value + + ) == SL_STATUS_OK) { + return true; + } } - if (uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_is_supported(unid, endpoint_id)) { + + return false; +} + +static inline bool uic_mqtt_dotdot_groups_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_groups_write_attributes_callback) { + uic_mqtt_dotdot_groups_state_t groups_new_state = {}; + uic_mqtt_dotdot_groups_updated_state_t groups_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + groups_new_state, + groups_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_groups_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_groups_force_read_attributes_callback) { + uic_mqtt_dotdot_groups_updated_state_t groups_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + groups_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Groups Cluster +void uic_mqtt_dotdot_groups_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_groups_add_group_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetWeeklyScheduleResponse")"; + ss << R"("AddGroup")"; } - if (uic_mqtt_dotdot_thermostat_set_weekly_schedule_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_groups_add_group_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("SetWeeklySchedule")"; + ss << R"("AddGroupResponse")"; } - if (uic_mqtt_dotdot_thermostat_get_relay_status_log_response_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_groups_view_group_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetRelayStatusLogResponse")"; + ss << R"("ViewGroup")"; } - if (uic_mqtt_dotdot_thermostat_get_weekly_schedule_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_groups_view_group_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetWeeklySchedule")"; + ss << R"("ViewGroupResponse")"; } - if (uic_mqtt_dotdot_thermostat_clear_weekly_schedule_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_groups_get_group_membership_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ClearWeeklySchedule")"; + ss << R"("GetGroupMembership")"; } - if (uic_mqtt_dotdot_thermostat_get_relay_status_log_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_groups_get_group_membership_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetRelayStatusLog")"; + ss << R"("GetGroupMembershipResponse")"; + } + if (uic_mqtt_dotdot_groups_remove_group_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("RemoveGroup")"; + } + if (uic_mqtt_dotdot_groups_remove_group_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("RemoveGroupResponse")"; + } + if (uic_mqtt_dotdot_groups_remove_all_groups_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("RemoveAllGroups")"; + } + if (uic_mqtt_dotdot_groups_add_group_if_identifying_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("AddGroupIfIdentifying")"; } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_thermostat_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_groups_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -104680,7 +103450,7 @@ void uic_mqtt_dotdot_thermostat_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_thermostat_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_groups_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -104691,7 +103461,7 @@ void uic_mqtt_dotdot_thermostat_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Thermostat/SupportedCommands"; + topic += "/Groups/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -104703,7 +103473,7 @@ void uic_mqtt_dotdot_thermostat_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Thermostat/Attributes"; + attributes_topic += "/Groups/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104714,14 +103484,14 @@ void uic_mqtt_dotdot_thermostat_publish_supported_commands( } } -// Publishing empty/no Supported Commands for Thermostat Cluster -void uic_mqtt_dotdot_thermostat_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Groups Cluster +void uic_mqtt_dotdot_groups_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Thermostat/SupportedCommands"; + topic += "/Groups/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -104731,10 +103501,10 @@ void uic_mqtt_dotdot_thermostat_publish_empty_supported_commands( } } -// Publishing Cluster Revision for FanControl Cluster -void uic_mqtt_dotdot_fan_control_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Scenes Cluster +void uic_mqtt_dotdot_scenes_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/FanControl/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Scenes/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -104751,13 +103521,13 @@ void uic_mqtt_dotdot_fan_control_publish_cluster_revision(const char* base_topic true); } -// Unretain Cluster Revision for FanControl Cluster -void uic_mqtt_dotdot_fan_control_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Scenes Cluster +void uic_mqtt_dotdot_scenes_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/FanControl/Attributes/ClusterRevision"; + + "/Scenes/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -104767,476 +103537,280 @@ void uic_mqtt_dotdot_fan_control_unretain_cluster_revision(const char* base_topi // clang-format off } - -static inline bool uic_mqtt_dotdot_fan_control_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_scenes_add_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_fan_control_write_attributes_callback) { - uic_mqtt_dotdot_fan_control_state_t fan_control_new_state = {}; - uic_mqtt_dotdot_fan_control_updated_state_t fan_control_new_updated_state = {}; + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + SSceneName scene_name_value; + memset(&scene_name_value, 0x00, sizeof(scene_name_value)); + uint8_t transition_time100ms_value; + memset(&transition_time100ms_value, 0x00, sizeof(transition_time100ms_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_add_scene_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + groupid_value, + + sceneid_value, + + transition_time_value, + + scene_name_value, + + 0, nullptr, - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - fan_control_new_state, - fan_control_new_updated_state - ) == SL_STATUS_OK) { + transition_time100ms_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_fan_control_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_scenes_add_scene_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_fan_control_force_read_attributes_callback) { - uic_mqtt_dotdot_fan_control_updated_state_t fan_control_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - fan_control_force_update - ) == SL_STATUS_OK) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_add_scene_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + groupid_value, + + sceneid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for FanControl Cluster -void uic_mqtt_dotdot_fan_control_publish_supported_commands( +static inline bool uic_mqtt_dotdot_scenes_view_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_fan_control_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_fan_control_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_view_scene_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + groupid_value, + + sceneid_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/FanControl/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/FanControl/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for FanControl Cluster -void uic_mqtt_dotdot_fan_control_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_scenes_view_scene_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/FanControl/SupportedCommands"; + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + SSceneName scene_name_value; + memset(&scene_name_value, 0x00, sizeof(scene_name_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_view_scene_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + groupid_value, + + sceneid_value, + + transition_time_value, + + scene_name_value, + + 0, nullptr - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + ) == SL_STATUS_OK) { + return true; + } } -} -// Publishing Cluster Revision for DehumidificationControl Cluster -void uic_mqtt_dotdot_dehumidification_control_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/DehumidificationControl/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for DehumidificationControl Cluster -void uic_mqtt_dotdot_dehumidification_control_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/DehumidificationControl/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_dehumidification_control_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_scenes_remove_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_dehumidification_control_write_attributes_callback) { - uic_mqtt_dotdot_dehumidification_control_state_t dehumidification_control_new_state = {}; - uic_mqtt_dotdot_dehumidification_control_updated_state_t dehumidification_control_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - dehumidification_control_new_state, - dehumidification_control_new_updated_state - ) == SL_STATUS_OK) { + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_remove_scene_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + groupid_value, + + sceneid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_dehumidification_control_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_scenes_remove_scene_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_dehumidification_control_force_read_attributes_callback) { - uic_mqtt_dotdot_dehumidification_control_updated_state_t dehumidification_control_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - dehumidification_control_force_update - ) == SL_STATUS_OK) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_remove_scene_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + groupid_value, + + sceneid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for DehumidificationControl Cluster -void uic_mqtt_dotdot_dehumidification_control_publish_supported_commands( +static inline bool uic_mqtt_dotdot_scenes_remove_all_scenes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_dehumidification_control_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_remove_all_scenes_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + groupid_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_dehumidification_control_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_scenes_remove_all_scenes_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_remove_all_scenes_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + groupid_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/DehumidificationControl/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/DehumidificationControl/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + return false; +} +static inline bool uic_mqtt_dotdot_scenes_store_scene_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_store_scene_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + groupid_value, + + sceneid_value + + ) == SL_STATUS_OK) { + return true; } } -} -// Publishing empty/no Supported Commands for DehumidificationControl Cluster -void uic_mqtt_dotdot_dehumidification_control_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) + return false; +} +static inline bool uic_mqtt_dotdot_scenes_store_scene_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/DehumidificationControl/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } -} - -// Publishing Cluster Revision for ThermostatUserInterfaceConfiguration Cluster -void uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/ThermostatUserInterfaceConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for ThermostatUserInterfaceConfiguration Cluster -void uic_mqtt_dotdot_thermostat_user_interface_configuration_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/ThermostatUserInterfaceConfiguration/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - - -static inline bool uic_mqtt_dotdot_thermostat_user_interface_configuration_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_thermostat_user_interface_configuration_write_attributes_callback) { - uic_mqtt_dotdot_thermostat_user_interface_configuration_state_t thermostat_user_interface_configuration_new_state = {}; - uic_mqtt_dotdot_thermostat_user_interface_configuration_updated_state_t thermostat_user_interface_configuration_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - thermostat_user_interface_configuration_new_state, - thermostat_user_interface_configuration_new_updated_state - ) == SL_STATUS_OK) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_store_scene_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + groupid_value, + + sceneid_value + + ) == SL_STATUS_OK) { return true; } } - return false; -} -static inline bool uic_mqtt_dotdot_thermostat_user_interface_configuration_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_thermostat_user_interface_configuration_force_read_attributes_callback) { - uic_mqtt_dotdot_thermostat_user_interface_configuration_updated_state_t thermostat_user_interface_configuration_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - thermostat_user_interface_configuration_force_update - ) == SL_STATUS_OK) { - return true; - } - } return false; } - -// Publishing Supported Commands for ThermostatUserInterfaceConfiguration Cluster -void uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_thermostat_user_interface_configuration_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_thermostat_user_interface_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ThermostatUserInterfaceConfiguration/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/ThermostatUserInterfaceConfiguration/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } -} - -// Publishing empty/no Supported Commands for ThermostatUserInterfaceConfiguration Cluster -void uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ThermostatUserInterfaceConfiguration/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } -} - -// Publishing Cluster Revision for ColorControl Cluster -void uic_mqtt_dotdot_color_control_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/ColorControl/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for ColorControl Cluster -void uic_mqtt_dotdot_color_control_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/ColorControl/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - -static inline bool uic_mqtt_dotdot_color_control_move_to_hue_is_supported( +static inline bool uic_mqtt_dotdot_scenes_recall_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t hue_value; - memset(&hue_value, 0x00, sizeof(hue_value)); - CCDirection direction_value; - memset(&direction_value, 0x00, sizeof(direction_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); uint16_t transition_time_value; memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_hue_callback) { + for (const auto& callback: uic_mqtt_dotdot_scenes_recall_scene_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - hue_value, - - direction_value, - - transition_time_value, + groupid_value, - options_mask_value, + sceneid_value, - options_override_value + transition_time_value ) == SL_STATUS_OK) { return true; @@ -105245,28 +103819,16 @@ static inline bool uic_mqtt_dotdot_color_control_move_to_hue_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_move_hue_is_supported( +static inline bool uic_mqtt_dotdot_scenes_get_scene_membership_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - CCMoveMode move_mode_value; - memset(&move_mode_value, 0x00, sizeof(move_mode_value)); - uint8_t rate_value; - memset(&rate_value, 0x00, sizeof(rate_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_hue_callback) { + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_get_scene_membership_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - move_mode_value, - - rate_value, - - options_mask_value, - - options_override_value + groupid_value ) == SL_STATUS_OK) { return true; @@ -105275,33 +103837,27 @@ static inline bool uic_mqtt_dotdot_color_control_move_hue_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_step_hue_is_supported( +static inline bool uic_mqtt_dotdot_scenes_get_scene_membership_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - CCStepMode step_mode_value; - memset(&step_mode_value, 0x00, sizeof(step_mode_value)); - uint8_t step_size_value; - memset(&step_size_value, 0x00, sizeof(step_size_value)); - uint8_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_step_hue_callback) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint8_t capacity_value; + memset(&capacity_value, 0x00, sizeof(capacity_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_get_scene_membership_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - step_mode_value, - - step_size_value, - - transition_time_value, + status_value, - options_mask_value, + capacity_value, - options_override_value + groupid_value, + 0, nullptr + ) == SL_STATUS_OK) { return true; } @@ -105309,29 +103865,31 @@ static inline bool uic_mqtt_dotdot_color_control_step_hue_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_move_to_saturation_is_supported( +static inline bool uic_mqtt_dotdot_scenes_enhanced_add_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t saturation_value; - memset(&saturation_value, 0x00, sizeof(saturation_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); uint16_t transition_time_value; memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_saturation_callback) { + SSceneName scene_name_value; + memset(&scene_name_value, 0x00, sizeof(scene_name_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_add_scene_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - saturation_value, + groupid_value, - transition_time_value, + sceneid_value, - options_mask_value, + transition_time_value, - options_override_value + scene_name_value, + 0, nullptr + ) == SL_STATUS_OK) { return true; } @@ -105339,28 +103897,24 @@ static inline bool uic_mqtt_dotdot_color_control_move_to_saturation_is_supported return false; } -static inline bool uic_mqtt_dotdot_color_control_move_saturation_is_supported( +static inline bool uic_mqtt_dotdot_scenes_enhanced_add_scene_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - CCMoveMode move_mode_value; - memset(&move_mode_value, 0x00, sizeof(move_mode_value)); - uint8_t rate_value; - memset(&rate_value, 0x00, sizeof(rate_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_saturation_callback) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_add_scene_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - move_mode_value, - - rate_value, + status_value, - options_mask_value, + groupid_value, - options_override_value + sceneid_value ) == SL_STATUS_OK) { return true; @@ -105369,32 +103923,20 @@ static inline bool uic_mqtt_dotdot_color_control_move_saturation_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_step_saturation_is_supported( +static inline bool uic_mqtt_dotdot_scenes_enhanced_view_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - CCStepMode step_mode_value; - memset(&step_mode_value, 0x00, sizeof(step_mode_value)); - uint8_t step_size_value; - memset(&step_size_value, 0x00, sizeof(step_size_value)); - uint8_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_step_saturation_callback) { + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_view_scene_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - step_mode_value, - - step_size_value, - - transition_time_value, - - options_mask_value, + groupid_value, - options_override_value + sceneid_value ) == SL_STATUS_OK) { return true; @@ -105403,33 +103945,35 @@ static inline bool uic_mqtt_dotdot_color_control_step_saturation_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_is_supported( +static inline bool uic_mqtt_dotdot_scenes_enhanced_view_scene_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t hue_value; - memset(&hue_value, 0x00, sizeof(hue_value)); - uint8_t saturation_value; - memset(&saturation_value, 0x00, sizeof(saturation_value)); + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId groupid_value; + memset(&groupid_value, 0x00, sizeof(groupid_value)); + uint8_t sceneid_value; + memset(&sceneid_value, 0x00, sizeof(sceneid_value)); uint16_t transition_time_value; memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_callback) { + SSceneName scene_name_value; + memset(&scene_name_value, 0x00, sizeof(scene_name_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_enhanced_view_scene_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - hue_value, + status_value, - saturation_value, + groupid_value, - transition_time_value, + sceneid_value, - options_mask_value, + transition_time_value, - options_override_value + scene_name_value, + 0, nullptr + ) == SL_STATUS_OK) { return true; } @@ -105437,32 +103981,32 @@ static inline bool uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_is_s return false; } -static inline bool uic_mqtt_dotdot_color_control_move_to_color_is_supported( +static inline bool uic_mqtt_dotdot_scenes_copy_scene_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t colorx_value; - memset(&colorx_value, 0x00, sizeof(colorx_value)); - uint16_t colory_value; - memset(&colory_value, 0x00, sizeof(colory_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_color_callback) { + uint8_t mode_value; + memset(&mode_value, 0x00, sizeof(mode_value)); + SGroupId group_identifier_from_value; + memset(&group_identifier_from_value, 0x00, sizeof(group_identifier_from_value)); + uint8_t scene_identifier_from_value; + memset(&scene_identifier_from_value, 0x00, sizeof(scene_identifier_from_value)); + SGroupId group_identifier_to_value; + memset(&group_identifier_to_value, 0x00, sizeof(group_identifier_to_value)); + uint8_t scene_identifier_to_value; + memset(&scene_identifier_to_value, 0x00, sizeof(scene_identifier_to_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_copy_scene_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - colorx_value, + mode_value, - colory_value, + group_identifier_from_value, - transition_time_value, + scene_identifier_from_value, - options_mask_value, + group_identifier_to_value, - options_override_value + scene_identifier_to_value ) == SL_STATUS_OK) { return true; @@ -105471,28 +104015,24 @@ static inline bool uic_mqtt_dotdot_color_control_move_to_color_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_move_color_is_supported( +static inline bool uic_mqtt_dotdot_scenes_copy_scene_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - int16_t ratex_value; - memset(&ratex_value, 0x00, sizeof(ratex_value)); - int16_t ratey_value; - memset(&ratey_value, 0x00, sizeof(ratey_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_color_callback) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + SGroupId group_identifier_from_value; + memset(&group_identifier_from_value, 0x00, sizeof(group_identifier_from_value)); + uint8_t scene_identifier_from_value; + memset(&scene_identifier_from_value, 0x00, sizeof(scene_identifier_from_value)); + for (const auto& callback: uic_mqtt_dotdot_scenes_copy_scene_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - ratex_value, - - ratey_value, + status_value, - options_mask_value, + group_identifier_from_value, - options_override_value + scene_identifier_from_value ) == SL_STATUS_OK) { return true; @@ -105501,532 +104041,192 @@ static inline bool uic_mqtt_dotdot_color_control_move_color_is_supported( return false; } -static inline bool uic_mqtt_dotdot_color_control_step_color_is_supported( + +static inline bool uic_mqtt_dotdot_scenes_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - int16_t stepx_value; - memset(&stepx_value, 0x00, sizeof(stepx_value)); - int16_t stepy_value; - memset(&stepy_value, 0x00, sizeof(stepy_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_step_color_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - stepx_value, - - stepy_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_scenes_write_attributes_callback) { + uic_mqtt_dotdot_scenes_state_t scenes_new_state = {}; + uic_mqtt_dotdot_scenes_updated_state_t scenes_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + scenes_new_state, + scenes_new_updated_state + ) == SL_STATUS_OK) { return true; } } - return false; } -static inline bool uic_mqtt_dotdot_color_control_move_to_color_temperature_is_supported( + +static inline bool uic_mqtt_dotdot_scenes_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t color_temperature_mireds_value; - memset(&color_temperature_mireds_value, 0x00, sizeof(color_temperature_mireds_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_color_temperature_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - color_temperature_mireds_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_scenes_force_read_attributes_callback) { + uic_mqtt_dotdot_scenes_updated_state_t scenes_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + scenes_force_update + ) == SL_STATUS_OK) { return true; } } - return false; } -static inline bool uic_mqtt_dotdot_color_control_enhanced_move_to_hue_is_supported( + +// Publishing Supported Commands for Scenes Cluster +void uic_mqtt_dotdot_scenes_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t enhanced_hue_value; - memset(&enhanced_hue_value, 0x00, sizeof(enhanced_hue_value)); - CCDirection direction_value; - memset(&direction_value, 0x00, sizeof(direction_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_move_to_hue_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - enhanced_hue_value, - - direction_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_scenes_add_scene_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("AddScene")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_enhanced_move_hue_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - CCMoveMode move_mode_value; - memset(&move_mode_value, 0x00, sizeof(move_mode_value)); - uint16_t rate_value; - memset(&rate_value, 0x00, sizeof(rate_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_move_hue_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - move_mode_value, - - rate_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_scenes_add_scene_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("AddSceneResponse")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_enhanced_step_hue_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - CCStepMode step_mode_value; - memset(&step_mode_value, 0x00, sizeof(step_mode_value)); - uint16_t step_size_value; - memset(&step_size_value, 0x00, sizeof(step_size_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_step_hue_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - step_mode_value, - - step_size_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_scenes_view_scene_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ViewScene")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_enhanced_move_to_hue_and_saturation_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t enhanced_hue_value; - memset(&enhanced_hue_value, 0x00, sizeof(enhanced_hue_value)); - uint8_t saturation_value; - memset(&saturation_value, 0x00, sizeof(saturation_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_move_to_hue_and_saturation_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - enhanced_hue_value, - - saturation_value, - - transition_time_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_scenes_view_scene_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ViewSceneResponse")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_color_loop_set_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t update_flags_value; - memset(&update_flags_value, 0x00, sizeof(update_flags_value)); - ColorLoopSetAction action_value; - memset(&action_value, 0x00, sizeof(action_value)); - CCColorLoopDirection direction_value; - memset(&direction_value, 0x00, sizeof(direction_value)); - uint16_t time_value; - memset(&time_value, 0x00, sizeof(time_value)); - uint16_t start_hue_value; - memset(&start_hue_value, 0x00, sizeof(start_hue_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_color_loop_set_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - update_flags_value, - - action_value, - - direction_value, - - time_value, - - start_hue_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_scenes_remove_scene_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("RemoveScene")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_stop_move_step_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_stop_move_step_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_scenes_remove_scene_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("RemoveSceneResponse")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_move_color_temperature_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - CCMoveMode move_mode_value; - memset(&move_mode_value, 0x00, sizeof(move_mode_value)); - uint16_t rate_value; - memset(&rate_value, 0x00, sizeof(rate_value)); - CCMinMiredsField color_temperature_minimum_mireds_value; - memset(&color_temperature_minimum_mireds_value, 0x00, sizeof(color_temperature_minimum_mireds_value)); - CCMaxMiredsField color_temperature_maximum_mireds_value; - memset(&color_temperature_maximum_mireds_value, 0x00, sizeof(color_temperature_maximum_mireds_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_move_color_temperature_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - move_mode_value, - - rate_value, - - color_temperature_minimum_mireds_value, - - color_temperature_maximum_mireds_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_color_control_step_color_temperature_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - CCStepMode step_mode_value; - memset(&step_mode_value, 0x00, sizeof(step_mode_value)); - uint16_t step_size_value; - memset(&step_size_value, 0x00, sizeof(step_size_value)); - uint16_t transition_time_value; - memset(&transition_time_value, 0x00, sizeof(transition_time_value)); - CCMinMiredsField color_temperature_minimum_mireds_value; - memset(&color_temperature_minimum_mireds_value, 0x00, sizeof(color_temperature_minimum_mireds_value)); - CCMaxMiredsField color_temperature_maximum_mireds_value; - memset(&color_temperature_maximum_mireds_value, 0x00, sizeof(color_temperature_maximum_mireds_value)); - uint8_t options_mask_value; - memset(&options_mask_value, 0x00, sizeof(options_mask_value)); - uint8_t options_override_value; - memset(&options_override_value, 0x00, sizeof(options_override_value)); - for (const auto& callback: uic_mqtt_dotdot_color_control_step_color_temperature_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - step_mode_value, - - step_size_value, - - transition_time_value, - - color_temperature_minimum_mireds_value, - - color_temperature_maximum_mireds_value, - - options_mask_value, - - options_override_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} - -static inline bool uic_mqtt_dotdot_color_control_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_color_control_write_attributes_callback) { - uic_mqtt_dotdot_color_control_state_t color_control_new_state = {}; - uic_mqtt_dotdot_color_control_updated_state_t color_control_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - color_control_new_state, - color_control_new_updated_state - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} - -static inline bool uic_mqtt_dotdot_color_control_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_color_control_force_read_attributes_callback) { - uic_mqtt_dotdot_color_control_updated_state_t color_control_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - color_control_force_update - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} - -// Publishing Supported Commands for ColorControl Cluster -void uic_mqtt_dotdot_color_control_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_color_control_move_to_hue_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveToHue")"; - } - if (uic_mqtt_dotdot_color_control_move_hue_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveHue")"; - } - if (uic_mqtt_dotdot_color_control_step_hue_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StepHue")"; - } - if (uic_mqtt_dotdot_color_control_move_to_saturation_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveToSaturation")"; - } - if (uic_mqtt_dotdot_color_control_move_saturation_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("MoveSaturation")"; - } - if (uic_mqtt_dotdot_color_control_step_saturation_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StepSaturation")"; - } - if (uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_remove_all_scenes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("MoveToHueAndSaturation")"; + ss << R"("RemoveAllScenes")"; } - if (uic_mqtt_dotdot_color_control_move_to_color_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_remove_all_scenes_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("MoveToColor")"; + ss << R"("RemoveAllScenesResponse")"; } - if (uic_mqtt_dotdot_color_control_move_color_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_store_scene_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("MoveColor")"; + ss << R"("StoreScene")"; } - if (uic_mqtt_dotdot_color_control_step_color_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_store_scene_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("StepColor")"; + ss << R"("StoreSceneResponse")"; } - if (uic_mqtt_dotdot_color_control_move_to_color_temperature_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_recall_scene_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("MoveToColorTemperature")"; + ss << R"("RecallScene")"; } - if (uic_mqtt_dotdot_color_control_enhanced_move_to_hue_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_get_scene_membership_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("EnhancedMoveToHue")"; + ss << R"("GetSceneMembership")"; } - if (uic_mqtt_dotdot_color_control_enhanced_move_hue_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_get_scene_membership_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("EnhancedMoveHue")"; + ss << R"("GetSceneMembershipResponse")"; } - if (uic_mqtt_dotdot_color_control_enhanced_step_hue_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_enhanced_add_scene_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("EnhancedStepHue")"; + ss << R"("EnhancedAddScene")"; } - if (uic_mqtt_dotdot_color_control_enhanced_move_to_hue_and_saturation_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_enhanced_add_scene_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("EnhancedMoveToHueAndSaturation")"; + ss << R"("EnhancedAddSceneResponse")"; } - if (uic_mqtt_dotdot_color_control_color_loop_set_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_enhanced_view_scene_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ColorLoopSet")"; + ss << R"("EnhancedViewScene")"; } - if (uic_mqtt_dotdot_color_control_stop_move_step_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_enhanced_view_scene_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("StopMoveStep")"; + ss << R"("EnhancedViewSceneResponse")"; } - if (uic_mqtt_dotdot_color_control_move_color_temperature_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_copy_scene_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("MoveColorTemperature")"; + ss << R"("CopyScene")"; } - if (uic_mqtt_dotdot_color_control_step_color_temperature_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_copy_scene_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("StepColorTemperature")"; + ss << R"("CopySceneResponse")"; } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_color_control_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_scenes_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106035,7 +104235,7 @@ void uic_mqtt_dotdot_color_control_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_color_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_scenes_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106046,7 +104246,7 @@ void uic_mqtt_dotdot_color_control_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ColorControl/SupportedCommands"; + topic += "/Scenes/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -106058,7 +104258,7 @@ void uic_mqtt_dotdot_color_control_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/ColorControl/Attributes"; + attributes_topic += "/Scenes/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106069,14 +104269,14 @@ void uic_mqtt_dotdot_color_control_publish_supported_commands( } } -// Publishing empty/no Supported Commands for ColorControl Cluster -void uic_mqtt_dotdot_color_control_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Scenes Cluster +void uic_mqtt_dotdot_scenes_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ColorControl/SupportedCommands"; + topic += "/Scenes/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106086,10 +104286,10 @@ void uic_mqtt_dotdot_color_control_publish_empty_supported_commands( } } -// Publishing Cluster Revision for BallastConfiguration Cluster -void uic_mqtt_dotdot_ballast_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for OnOff Cluster +void uic_mqtt_dotdot_on_off_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/BallastConfiguration/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/OnOff/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -106106,13 +104306,13 @@ void uic_mqtt_dotdot_ballast_configuration_publish_cluster_revision(const char* true); } -// Unretain Cluster Revision for BallastConfiguration Cluster -void uic_mqtt_dotdot_ballast_configuration_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for OnOff Cluster +void uic_mqtt_dotdot_on_off_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/BallastConfiguration/Attributes/ClusterRevision"; + + "/OnOff/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -106122,169 +104322,125 @@ void uic_mqtt_dotdot_ballast_configuration_unretain_cluster_revision(const char* // clang-format off } - -static inline bool uic_mqtt_dotdot_ballast_configuration_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_on_off_off_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ballast_configuration_write_attributes_callback) { - uic_mqtt_dotdot_ballast_configuration_state_t ballast_configuration_new_state = {}; - uic_mqtt_dotdot_ballast_configuration_updated_state_t ballast_configuration_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - ballast_configuration_new_state, - ballast_configuration_new_updated_state - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_on_off_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_ballast_configuration_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_on_off_on_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ballast_configuration_force_read_attributes_callback) { - uic_mqtt_dotdot_ballast_configuration_updated_state_t ballast_configuration_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - ballast_configuration_force_update - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_on_off_on_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for BallastConfiguration Cluster -void uic_mqtt_dotdot_ballast_configuration_publish_supported_commands( +static inline bool uic_mqtt_dotdot_on_off_toggle_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_ballast_configuration_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + for (const auto& callback: uic_mqtt_dotdot_on_off_toggle_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_ballast_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_on_off_off_with_effect_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + OffWithEffectEffectIdentifier effect_identifier_value; + memset(&effect_identifier_value, 0x00, sizeof(effect_identifier_value)); + uint8_t effect_variant_value; + memset(&effect_variant_value, 0x00, sizeof(effect_variant_value)); + for (const auto& callback: uic_mqtt_dotdot_on_off_off_with_effect_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + effect_identifier_value, + + effect_variant_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/BallastConfiguration/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/BallastConfiguration/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for BallastConfiguration Cluster -void uic_mqtt_dotdot_ballast_configuration_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_on_off_on_with_recall_global_scene_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/BallastConfiguration/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + for (const auto& callback: uic_mqtt_dotdot_on_off_on_with_recall_global_scene_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } } -} -// Publishing Cluster Revision for IlluminanceMeasurement Cluster -void uic_mqtt_dotdot_illuminance_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/IlluminanceMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + return false; } - -// Unretain Cluster Revision for IlluminanceMeasurement Cluster -void uic_mqtt_dotdot_illuminance_measurement_unretain_cluster_revision(const char* base_topic) +static inline bool uic_mqtt_dotdot_on_off_on_with_timed_off_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/IlluminanceMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + uint8_t on_off_control_value; + memset(&on_off_control_value, 0x00, sizeof(on_off_control_value)); + uint16_t on_time_value; + memset(&on_time_value, 0x00, sizeof(on_time_value)); + uint16_t off_wait_time_value; + memset(&off_wait_time_value, 0x00, sizeof(off_wait_time_value)); + for (const auto& callback: uic_mqtt_dotdot_on_off_on_with_timed_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + on_off_control_value, + + on_time_value, + + off_wait_time_value + + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} -static inline bool uic_mqtt_dotdot_illuminance_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_on_off_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_illuminance_measurement_write_attributes_callback) { - uic_mqtt_dotdot_illuminance_measurement_state_t illuminance_measurement_new_state = {}; - uic_mqtt_dotdot_illuminance_measurement_updated_state_t illuminance_measurement_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_on_off_write_attributes_callback) { + uic_mqtt_dotdot_on_off_state_t on_off_new_state = {}; + uic_mqtt_dotdot_on_off_updated_state_t on_off_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - illuminance_measurement_new_state, - illuminance_measurement_new_updated_state + on_off_new_state, + on_off_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -106292,17 +104448,17 @@ static inline bool uic_mqtt_dotdot_illuminance_measurement_write_attributes_is_s return false; } -static inline bool uic_mqtt_dotdot_illuminance_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_on_off_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_illuminance_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_illuminance_measurement_updated_state_t illuminance_measurement_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_on_off_force_read_attributes_callback) { + uic_mqtt_dotdot_on_off_updated_state_t on_off_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - illuminance_measurement_force_update + on_off_force_update ) == SL_STATUS_OK) { return true; } @@ -106310,8 +104466,8 @@ static inline bool uic_mqtt_dotdot_illuminance_measurement_force_read_attributes return false; } -// Publishing Supported Commands for IlluminanceMeasurement Cluster -void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( +// Publishing Supported Commands for OnOff Cluster +void uic_mqtt_dotdot_on_off_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -106320,9 +104476,51 @@ void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( ss.str(""); // check if there is callback for each command + if (uic_mqtt_dotdot_on_off_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Off")"; + } + if (uic_mqtt_dotdot_on_off_on_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("On")"; + } + if (uic_mqtt_dotdot_on_off_toggle_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Toggle")"; + } + if (uic_mqtt_dotdot_on_off_off_with_effect_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("OffWithEffect")"; + } + if (uic_mqtt_dotdot_on_off_on_with_recall_global_scene_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("OnWithRecallGlobalScene")"; + } + if (uic_mqtt_dotdot_on_off_on_with_timed_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("OnWithTimedOff")"; + } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_illuminance_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_on_off_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106331,7 +104529,7 @@ void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_illuminance_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_on_off_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106342,7 +104540,7 @@ void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IlluminanceMeasurement/SupportedCommands"; + topic += "/OnOff/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -106354,7 +104552,7 @@ void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/IlluminanceMeasurement/Attributes"; + attributes_topic += "/OnOff/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106365,14 +104563,14 @@ void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( } } -// Publishing empty/no Supported Commands for IlluminanceMeasurement Cluster -void uic_mqtt_dotdot_illuminance_measurement_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for OnOff Cluster +void uic_mqtt_dotdot_on_off_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IlluminanceMeasurement/SupportedCommands"; + topic += "/OnOff/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106382,10 +104580,10 @@ void uic_mqtt_dotdot_illuminance_measurement_publish_empty_supported_commands( } } -// Publishing Cluster Revision for IlluminanceLevelSensing Cluster -void uic_mqtt_dotdot_illuminance_level_sensing_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Level Cluster +void uic_mqtt_dotdot_level_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/IlluminanceLevelSensing/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Level/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -106402,13 +104600,13 @@ void uic_mqtt_dotdot_illuminance_level_sensing_publish_cluster_revision(const ch true); } -// Unretain Cluster Revision for IlluminanceLevelSensing Cluster -void uic_mqtt_dotdot_illuminance_level_sensing_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Level Cluster +void uic_mqtt_dotdot_level_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/IlluminanceLevelSensing/Attributes/ClusterRevision"; + + "/Level/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -106418,196 +104616,298 @@ void uic_mqtt_dotdot_illuminance_level_sensing_unretain_cluster_revision(const c // clang-format off } - -static inline bool uic_mqtt_dotdot_illuminance_level_sensing_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_level_move_to_level_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_illuminance_level_sensing_write_attributes_callback) { - uic_mqtt_dotdot_illuminance_level_sensing_state_t illuminance_level_sensing_new_state = {}; - uic_mqtt_dotdot_illuminance_level_sensing_updated_state_t illuminance_level_sensing_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - illuminance_level_sensing_new_state, - illuminance_level_sensing_new_updated_state - ) == SL_STATUS_OK) { + uint8_t level_value; + memset(&level_value, 0x00, sizeof(level_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_move_to_level_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + level_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_illuminance_level_sensing_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_level_move_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_illuminance_level_sensing_force_read_attributes_callback) { - uic_mqtt_dotdot_illuminance_level_sensing_updated_state_t illuminance_level_sensing_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - illuminance_level_sensing_force_update - ) == SL_STATUS_OK) { + MoveStepMode move_mode_value; + memset(&move_mode_value, 0x00, sizeof(move_mode_value)); + uint8_t rate_value; + memset(&rate_value, 0x00, sizeof(rate_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_move_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + move_mode_value, + + rate_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for IlluminanceLevelSensing Cluster -void uic_mqtt_dotdot_illuminance_level_sensing_publish_supported_commands( +static inline bool uic_mqtt_dotdot_level_step_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_illuminance_level_sensing_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_illuminance_level_sensing_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IlluminanceLevelSensing/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/IlluminanceLevelSensing/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + MoveStepMode step_mode_value; + memset(&step_mode_value, 0x00, sizeof(step_mode_value)); + uint8_t step_size_value; + memset(&step_size_value, 0x00, sizeof(step_size_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_step_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + step_mode_value, + + step_size_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; } } -} - -// Publishing empty/no Supported Commands for IlluminanceLevelSensing Cluster -void uic_mqtt_dotdot_illuminance_level_sensing_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IlluminanceLevelSensing/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } -} - -// Publishing Cluster Revision for TemperatureMeasurement Cluster -void uic_mqtt_dotdot_temperature_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/TemperatureMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for TemperatureMeasurement Cluster -void uic_mqtt_dotdot_temperature_measurement_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/TemperatureMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_temperature_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_level_stop_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_temperature_measurement_write_attributes_callback) { - uic_mqtt_dotdot_temperature_measurement_state_t temperature_measurement_new_state = {}; - uic_mqtt_dotdot_temperature_measurement_updated_state_t temperature_measurement_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - temperature_measurement_new_state, - temperature_measurement_new_updated_state - ) == SL_STATUS_OK) { + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_stop_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_temperature_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_level_move_to_level_with_on_off_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_temperature_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_temperature_measurement_updated_state_t temperature_measurement_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - temperature_measurement_force_update - ) == SL_STATUS_OK) { + uint8_t level_value; + memset(&level_value, 0x00, sizeof(level_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_move_to_level_with_on_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + level_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for TemperatureMeasurement Cluster -void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( +static inline bool uic_mqtt_dotdot_level_move_with_on_off_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + MoveStepMode move_mode_value; + memset(&move_mode_value, 0x00, sizeof(move_mode_value)); + uint8_t rate_value; + memset(&rate_value, 0x00, sizeof(rate_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_move_with_on_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + move_mode_value, + + rate_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_level_step_with_on_off_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + MoveStepMode step_mode_value; + memset(&step_mode_value, 0x00, sizeof(step_mode_value)); + uint8_t step_size_value; + memset(&step_size_value, 0x00, sizeof(step_size_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_step_with_on_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + step_mode_value, + + step_size_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_level_stop_with_on_off_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_level_stop_with_on_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_level_move_to_closest_frequency_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t frequency_value; + memset(&frequency_value, 0x00, sizeof(frequency_value)); + for (const auto& callback: uic_mqtt_dotdot_level_move_to_closest_frequency_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + frequency_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_level_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_level_write_attributes_callback) { + uic_mqtt_dotdot_level_state_t level_new_state = {}; + uic_mqtt_dotdot_level_updated_state_t level_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + level_new_state, + level_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_level_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_level_force_read_attributes_callback) { + uic_mqtt_dotdot_level_updated_state_t level_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + level_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Level Cluster +void uic_mqtt_dotdot_level_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -106616,9 +104916,72 @@ void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( ss.str(""); // check if there is callback for each command + if (uic_mqtt_dotdot_level_move_to_level_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToLevel")"; + } + if (uic_mqtt_dotdot_level_move_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Move")"; + } + if (uic_mqtt_dotdot_level_step_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Step")"; + } + if (uic_mqtt_dotdot_level_stop_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Stop")"; + } + if (uic_mqtt_dotdot_level_move_to_level_with_on_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToLevelWithOnOff")"; + } + if (uic_mqtt_dotdot_level_move_with_on_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveWithOnOff")"; + } + if (uic_mqtt_dotdot_level_step_with_on_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StepWithOnOff")"; + } + if (uic_mqtt_dotdot_level_stop_with_on_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StopWithOnOff")"; + } + if (uic_mqtt_dotdot_level_move_to_closest_frequency_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToClosestFrequency")"; + } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_temperature_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_level_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106627,7 +104990,7 @@ void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_temperature_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_level_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106638,7 +105001,7 @@ void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/TemperatureMeasurement/SupportedCommands"; + topic += "/Level/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -106650,7 +105013,7 @@ void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/TemperatureMeasurement/Attributes"; + attributes_topic += "/Level/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106661,14 +105024,14 @@ void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( } } -// Publishing empty/no Supported Commands for TemperatureMeasurement Cluster -void uic_mqtt_dotdot_temperature_measurement_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Level Cluster +void uic_mqtt_dotdot_level_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/TemperatureMeasurement/SupportedCommands"; + topic += "/Level/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106678,10 +105041,10 @@ void uic_mqtt_dotdot_temperature_measurement_publish_empty_supported_commands( } } -// Publishing Cluster Revision for PressureMeasurement Cluster -void uic_mqtt_dotdot_pressure_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Alarms Cluster +void uic_mqtt_dotdot_alarms_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/PressureMeasurement/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Alarms/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -106698,13 +105061,13 @@ void uic_mqtt_dotdot_pressure_measurement_publish_cluster_revision(const char* b true); } -// Unretain Cluster Revision for PressureMeasurement Cluster -void uic_mqtt_dotdot_pressure_measurement_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Alarms Cluster +void uic_mqtt_dotdot_alarms_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/PressureMeasurement/Attributes/ClusterRevision"; + + "/Alarms/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -106714,21 +105077,137 @@ void uic_mqtt_dotdot_pressure_measurement_unretain_cluster_revision(const char* // clang-format off } - -static inline bool uic_mqtt_dotdot_pressure_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_alarms_reset_alarm_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_pressure_measurement_write_attributes_callback) { - uic_mqtt_dotdot_pressure_measurement_state_t pressure_measurement_new_state = {}; - uic_mqtt_dotdot_pressure_measurement_updated_state_t pressure_measurement_new_updated_state = {}; + uint8_t alarm_code_value; + memset(&alarm_code_value, 0x00, sizeof(alarm_code_value)); + clusterId cluster_identifier_value; + memset(&cluster_identifier_value, 0x00, sizeof(cluster_identifier_value)); + for (const auto& callback: uic_mqtt_dotdot_alarms_reset_alarm_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + alarm_code_value, + + cluster_identifier_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_alarms_alarm_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t alarm_code_value; + memset(&alarm_code_value, 0x00, sizeof(alarm_code_value)); + clusterId cluster_identifier_value; + memset(&cluster_identifier_value, 0x00, sizeof(cluster_identifier_value)); + for (const auto& callback: uic_mqtt_dotdot_alarms_alarm_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + alarm_code_value, + + cluster_identifier_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_alarms_reset_all_alarms_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_alarms_reset_all_alarms_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_alarms_get_alarm_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint8_t alarm_code_value; + memset(&alarm_code_value, 0x00, sizeof(alarm_code_value)); + clusterId cluster_identifier_value; + memset(&cluster_identifier_value, 0x00, sizeof(cluster_identifier_value)); + uint32_t time_stamp_value; + memset(&time_stamp_value, 0x00, sizeof(time_stamp_value)); + for (const auto& callback: uic_mqtt_dotdot_alarms_get_alarm_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value, + + alarm_code_value, + + cluster_identifier_value, + + time_stamp_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_alarms_get_alarm_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_alarms_get_alarm_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_alarms_reset_alarm_log_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_alarms_reset_alarm_log_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_alarms_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_alarms_write_attributes_callback) { + uic_mqtt_dotdot_alarms_state_t alarms_new_state = {}; + uic_mqtt_dotdot_alarms_updated_state_t alarms_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - pressure_measurement_new_state, - pressure_measurement_new_updated_state + alarms_new_state, + alarms_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -106736,17 +105215,17 @@ static inline bool uic_mqtt_dotdot_pressure_measurement_write_attributes_is_supp return false; } -static inline bool uic_mqtt_dotdot_pressure_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_alarms_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_pressure_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_pressure_measurement_updated_state_t pressure_measurement_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_alarms_force_read_attributes_callback) { + uic_mqtt_dotdot_alarms_updated_state_t alarms_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - pressure_measurement_force_update + alarms_force_update ) == SL_STATUS_OK) { return true; } @@ -106754,8 +105233,8 @@ static inline bool uic_mqtt_dotdot_pressure_measurement_force_read_attributes_is return false; } -// Publishing Supported Commands for PressureMeasurement Cluster -void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( +// Publishing Supported Commands for Alarms Cluster +void uic_mqtt_dotdot_alarms_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -106764,9 +105243,51 @@ void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( ss.str(""); // check if there is callback for each command + if (uic_mqtt_dotdot_alarms_reset_alarm_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ResetAlarm")"; + } + if (uic_mqtt_dotdot_alarms_alarm_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Alarm")"; + } + if (uic_mqtt_dotdot_alarms_reset_all_alarms_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ResetAllAlarms")"; + } + if (uic_mqtt_dotdot_alarms_get_alarm_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetAlarmResponse")"; + } + if (uic_mqtt_dotdot_alarms_get_alarm_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetAlarm")"; + } + if (uic_mqtt_dotdot_alarms_reset_alarm_log_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ResetAlarmLog")"; + } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_pressure_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_alarms_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106775,7 +105296,7 @@ void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_pressure_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_alarms_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106786,7 +105307,7 @@ void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PressureMeasurement/SupportedCommands"; + topic += "/Alarms/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -106798,7 +105319,7 @@ void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/PressureMeasurement/Attributes"; + attributes_topic += "/Alarms/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106809,14 +105330,14 @@ void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( } } -// Publishing empty/no Supported Commands for PressureMeasurement Cluster -void uic_mqtt_dotdot_pressure_measurement_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Alarms Cluster +void uic_mqtt_dotdot_alarms_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PressureMeasurement/SupportedCommands"; + topic += "/Alarms/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106826,10 +105347,10 @@ void uic_mqtt_dotdot_pressure_measurement_publish_empty_supported_commands( } } -// Publishing Cluster Revision for FlowMeasurement Cluster -void uic_mqtt_dotdot_flow_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Time Cluster +void uic_mqtt_dotdot_time_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/FlowMeasurement/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Time/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -106846,13 +105367,13 @@ void uic_mqtt_dotdot_flow_measurement_publish_cluster_revision(const char* base_ true); } -// Unretain Cluster Revision for FlowMeasurement Cluster -void uic_mqtt_dotdot_flow_measurement_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Time Cluster +void uic_mqtt_dotdot_time_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/FlowMeasurement/Attributes/ClusterRevision"; + + "/Time/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -106863,20 +105384,20 @@ void uic_mqtt_dotdot_flow_measurement_unretain_cluster_revision(const char* base } -static inline bool uic_mqtt_dotdot_flow_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_time_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_flow_measurement_write_attributes_callback) { - uic_mqtt_dotdot_flow_measurement_state_t flow_measurement_new_state = {}; - uic_mqtt_dotdot_flow_measurement_updated_state_t flow_measurement_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_time_write_attributes_callback) { + uic_mqtt_dotdot_time_state_t time_new_state = {}; + uic_mqtt_dotdot_time_updated_state_t time_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - flow_measurement_new_state, - flow_measurement_new_updated_state + time_new_state, + time_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -106884,17 +105405,17 @@ static inline bool uic_mqtt_dotdot_flow_measurement_write_attributes_is_supporte return false; } -static inline bool uic_mqtt_dotdot_flow_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_time_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_flow_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_flow_measurement_updated_state_t flow_measurement_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_time_force_read_attributes_callback) { + uic_mqtt_dotdot_time_updated_state_t time_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - flow_measurement_force_update + time_force_update ) == SL_STATUS_OK) { return true; } @@ -106902,8 +105423,8 @@ static inline bool uic_mqtt_dotdot_flow_measurement_force_read_attributes_is_sup return false; } -// Publishing Supported Commands for FlowMeasurement Cluster -void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( +// Publishing Supported Commands for Time Cluster +void uic_mqtt_dotdot_time_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -106914,7 +105435,7 @@ void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( // check if there is callback for each command // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_flow_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_time_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106923,7 +105444,7 @@ void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_flow_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_time_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -106934,7 +105455,7 @@ void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/FlowMeasurement/SupportedCommands"; + topic += "/Time/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -106946,7 +105467,7 @@ void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/FlowMeasurement/Attributes"; + attributes_topic += "/Time/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106957,14 +105478,14 @@ void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( } } -// Publishing empty/no Supported Commands for FlowMeasurement Cluster -void uic_mqtt_dotdot_flow_measurement_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Time Cluster +void uic_mqtt_dotdot_time_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/FlowMeasurement/SupportedCommands"; + topic += "/Time/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -106974,10 +105495,10 @@ void uic_mqtt_dotdot_flow_measurement_publish_empty_supported_commands( } } -// Publishing Cluster Revision for RelativityHumidity Cluster -void uic_mqtt_dotdot_relativity_humidity_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for PollControl Cluster +void uic_mqtt_dotdot_poll_control_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/RelativityHumidity/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/PollControl/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -106994,13 +105515,13 @@ void uic_mqtt_dotdot_relativity_humidity_publish_cluster_revision(const char* ba true); } -// Unretain Cluster Revision for RelativityHumidity Cluster -void uic_mqtt_dotdot_relativity_humidity_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for PollControl Cluster +void uic_mqtt_dotdot_poll_control_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/RelativityHumidity/Attributes/ClusterRevision"; + + "/PollControl/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -107010,21 +105531,107 @@ void uic_mqtt_dotdot_relativity_humidity_unretain_cluster_revision(const char* b // clang-format off } - -static inline bool uic_mqtt_dotdot_relativity_humidity_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_poll_control_check_in_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_relativity_humidity_write_attributes_callback) { - uic_mqtt_dotdot_relativity_humidity_state_t relativity_humidity_new_state = {}; - uic_mqtt_dotdot_relativity_humidity_updated_state_t relativity_humidity_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_poll_control_check_in_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - relativity_humidity_new_state, - relativity_humidity_new_updated_state + return false; +} +static inline bool uic_mqtt_dotdot_poll_control_check_in_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + bool start_fast_polling_value; + memset(&start_fast_polling_value, 0x00, sizeof(start_fast_polling_value)); + uint16_t fast_poll_timeout_value; + memset(&fast_poll_timeout_value, 0x00, sizeof(fast_poll_timeout_value)); + for (const auto& callback: uic_mqtt_dotdot_poll_control_check_in_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + start_fast_polling_value, + + fast_poll_timeout_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_poll_control_fast_poll_stop_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_poll_control_fast_poll_stop_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_poll_control_set_long_poll_interval_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint32_t new_long_poll_interval_value; + memset(&new_long_poll_interval_value, 0x00, sizeof(new_long_poll_interval_value)); + for (const auto& callback: uic_mqtt_dotdot_poll_control_set_long_poll_interval_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + new_long_poll_interval_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_poll_control_set_short_poll_interval_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t new_short_poll_interval_value; + memset(&new_short_poll_interval_value, 0x00, sizeof(new_short_poll_interval_value)); + for (const auto& callback: uic_mqtt_dotdot_poll_control_set_short_poll_interval_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + new_short_poll_interval_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_poll_control_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_poll_control_write_attributes_callback) { + uic_mqtt_dotdot_poll_control_state_t poll_control_new_state = {}; + uic_mqtt_dotdot_poll_control_updated_state_t poll_control_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + poll_control_new_state, + poll_control_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -107032,17 +105639,17 @@ static inline bool uic_mqtt_dotdot_relativity_humidity_write_attributes_is_suppo return false; } -static inline bool uic_mqtt_dotdot_relativity_humidity_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_poll_control_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_relativity_humidity_force_read_attributes_callback) { - uic_mqtt_dotdot_relativity_humidity_updated_state_t relativity_humidity_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_poll_control_force_read_attributes_callback) { + uic_mqtt_dotdot_poll_control_updated_state_t poll_control_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - relativity_humidity_force_update + poll_control_force_update ) == SL_STATUS_OK) { return true; } @@ -107050,8 +105657,8 @@ static inline bool uic_mqtt_dotdot_relativity_humidity_force_read_attributes_is_ return false; } -// Publishing Supported Commands for RelativityHumidity Cluster -void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( +// Publishing Supported Commands for PollControl Cluster +void uic_mqtt_dotdot_poll_control_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -107060,9 +105667,44 @@ void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( ss.str(""); // check if there is callback for each command + if (uic_mqtt_dotdot_poll_control_check_in_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("CheckIn")"; + } + if (uic_mqtt_dotdot_poll_control_check_in_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("CheckInResponse")"; + } + if (uic_mqtt_dotdot_poll_control_fast_poll_stop_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("FastPollStop")"; + } + if (uic_mqtt_dotdot_poll_control_set_long_poll_interval_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetLongPollInterval")"; + } + if (uic_mqtt_dotdot_poll_control_set_short_poll_interval_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetShortPollInterval")"; + } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_relativity_humidity_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_poll_control_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -107071,7 +105713,7 @@ void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_relativity_humidity_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_poll_control_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -107082,7 +105724,7 @@ void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/RelativityHumidity/SupportedCommands"; + topic += "/PollControl/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -107094,7 +105736,7 @@ void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/RelativityHumidity/Attributes"; + attributes_topic += "/PollControl/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -107105,14 +105747,14 @@ void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( } } -// Publishing empty/no Supported Commands for RelativityHumidity Cluster -void uic_mqtt_dotdot_relativity_humidity_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for PollControl Cluster +void uic_mqtt_dotdot_poll_control_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/RelativityHumidity/SupportedCommands"; + topic += "/PollControl/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -107122,10 +105764,10 @@ void uic_mqtt_dotdot_relativity_humidity_publish_empty_supported_commands( } } -// Publishing Cluster Revision for OccupancySensing Cluster -void uic_mqtt_dotdot_occupancy_sensing_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for ShadeConfiguration Cluster +void uic_mqtt_dotdot_shade_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/OccupancySensing/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/ShadeConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -107142,13 +105784,13 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_cluster_revision(const char* base true); } -// Unretain Cluster Revision for OccupancySensing Cluster -void uic_mqtt_dotdot_occupancy_sensing_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for ShadeConfiguration Cluster +void uic_mqtt_dotdot_shade_configuration_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/OccupancySensing/Attributes/ClusterRevision"; + + "/ShadeConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -107159,20 +105801,20 @@ void uic_mqtt_dotdot_occupancy_sensing_unretain_cluster_revision(const char* bas } -static inline bool uic_mqtt_dotdot_occupancy_sensing_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_shade_configuration_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_occupancy_sensing_write_attributes_callback) { - uic_mqtt_dotdot_occupancy_sensing_state_t occupancy_sensing_new_state = {}; - uic_mqtt_dotdot_occupancy_sensing_updated_state_t occupancy_sensing_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_shade_configuration_write_attributes_callback) { + uic_mqtt_dotdot_shade_configuration_state_t shade_configuration_new_state = {}; + uic_mqtt_dotdot_shade_configuration_updated_state_t shade_configuration_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - occupancy_sensing_new_state, - occupancy_sensing_new_updated_state + shade_configuration_new_state, + shade_configuration_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -107180,17 +105822,17 @@ static inline bool uic_mqtt_dotdot_occupancy_sensing_write_attributes_is_support return false; } -static inline bool uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_shade_configuration_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_callback) { - uic_mqtt_dotdot_occupancy_sensing_updated_state_t occupancy_sensing_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_shade_configuration_force_read_attributes_callback) { + uic_mqtt_dotdot_shade_configuration_updated_state_t shade_configuration_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - occupancy_sensing_force_update + shade_configuration_force_update ) == SL_STATUS_OK) { return true; } @@ -107198,8 +105840,8 @@ static inline bool uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_is_su return false; } -// Publishing Supported Commands for OccupancySensing Cluster -void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( +// Publishing Supported Commands for ShadeConfiguration Cluster +void uic_mqtt_dotdot_shade_configuration_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -107210,7 +105852,7 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( // check if there is callback for each command // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_occupancy_sensing_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_shade_configuration_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -107219,7 +105861,7 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_shade_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -107230,7 +105872,7 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/OccupancySensing/SupportedCommands"; + topic += "/ShadeConfiguration/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -107242,7 +105884,7 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/OccupancySensing/Attributes"; + attributes_topic += "/ShadeConfiguration/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -107253,14 +105895,14 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( } } -// Publishing empty/no Supported Commands for OccupancySensing Cluster -void uic_mqtt_dotdot_occupancy_sensing_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for ShadeConfiguration Cluster +void uic_mqtt_dotdot_shade_configuration_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/OccupancySensing/SupportedCommands"; + topic += "/ShadeConfiguration/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -107270,10 +105912,10 @@ void uic_mqtt_dotdot_occupancy_sensing_publish_empty_supported_commands( } } -// Publishing Cluster Revision for SoilMoisture Cluster -void uic_mqtt_dotdot_soil_moisture_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for DoorLock Cluster +void uic_mqtt_dotdot_door_lock_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/SoilMoisture/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/DoorLock/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -107290,13 +105932,13 @@ void uic_mqtt_dotdot_soil_moisture_publish_cluster_revision(const char* base_top true); } -// Unretain Cluster Revision for SoilMoisture Cluster -void uic_mqtt_dotdot_soil_moisture_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for DoorLock Cluster +void uic_mqtt_dotdot_door_lock_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/SoilMoisture/Attributes/ClusterRevision"; + + "/DoorLock/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -107306,1056 +105948,828 @@ void uic_mqtt_dotdot_soil_moisture_unretain_cluster_revision(const char* base_to // clang-format off } - -static inline bool uic_mqtt_dotdot_soil_moisture_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_lock_door_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_soil_moisture_write_attributes_callback) { - uic_mqtt_dotdot_soil_moisture_state_t soil_moisture_new_state = {}; - uic_mqtt_dotdot_soil_moisture_updated_state_t soil_moisture_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - soil_moisture_new_state, - soil_moisture_new_updated_state - ) == SL_STATUS_OK) { + const char* pin_or_rfid_code_value; + memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_lock_door_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + pin_or_rfid_code_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_soil_moisture_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_lock_door_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_soil_moisture_force_read_attributes_callback) { - uic_mqtt_dotdot_soil_moisture_updated_state_t soil_moisture_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - soil_moisture_force_update - ) == SL_STATUS_OK) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_lock_door_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for SoilMoisture Cluster -void uic_mqtt_dotdot_soil_moisture_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_unlock_door_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_soil_moisture_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + const char* pin_or_rfid_code_value; + memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_door_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + pin_or_rfid_code_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_soil_moisture_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_unlock_door_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_door_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/SoilMoisture/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/SoilMoisture/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for SoilMoisture Cluster -void uic_mqtt_dotdot_soil_moisture_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_toggle_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/SoilMoisture/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + const char* pin_or_rfid_code_value; + memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_toggle_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + pin_or_rfid_code_value + + ) == SL_STATUS_OK) { + return true; + } } -} - -// Publishing Cluster Revision for PhMeasurement Cluster -void uic_mqtt_dotdot_ph_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/PhMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for PhMeasurement Cluster -void uic_mqtt_dotdot_ph_measurement_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/PhMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_ph_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_toggle_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ph_measurement_write_attributes_callback) { - uic_mqtt_dotdot_ph_measurement_state_t ph_measurement_new_state = {}; - uic_mqtt_dotdot_ph_measurement_updated_state_t ph_measurement_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - ph_measurement_new_state, - ph_measurement_new_updated_state - ) == SL_STATUS_OK) { + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_toggle_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_ph_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_unlock_with_timeout_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ph_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_ph_measurement_updated_state_t ph_measurement_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - ph_measurement_force_update - ) == SL_STATUS_OK) { + uint16_t timeout_in_seconds_value; + memset(&timeout_in_seconds_value, 0x00, sizeof(timeout_in_seconds_value)); + const char* pin_or_rfid_code_value; + memset(&pin_or_rfid_code_value, 0x00, sizeof(pin_or_rfid_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_with_timeout_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + timeout_in_seconds_value, + + pin_or_rfid_code_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for PhMeasurement Cluster -void uic_mqtt_dotdot_ph_measurement_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_unlock_with_timeout_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_ph_measurement_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_unlock_with_timeout_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_ph_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_get_log_record_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t log_index_value; + memset(&log_index_value, 0x00, sizeof(log_index_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_log_record_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + log_index_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PhMeasurement/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/PhMeasurement/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for PhMeasurement Cluster -void uic_mqtt_dotdot_ph_measurement_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_get_log_record_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PhMeasurement/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + uint16_t log_entryid_value; + memset(&log_entryid_value, 0x00, sizeof(log_entryid_value)); + uint32_t timestamp_value; + memset(×tamp_value, 0x00, sizeof(timestamp_value)); + GetLogRecordResponseEventType event_type_value; + memset(&event_type_value, 0x00, sizeof(event_type_value)); + DrlkOperEventSource source_operation_event_value; + memset(&source_operation_event_value, 0x00, sizeof(source_operation_event_value)); + uint8_t event_id_or_alarm_code_value; + memset(&event_id_or_alarm_code_value, 0x00, sizeof(event_id_or_alarm_code_value)); + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + const char* pin_value; + memset(&pin_value, 0x00, sizeof(pin_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_log_record_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + log_entryid_value, + + timestamp_value, + + event_type_value, + + source_operation_event_value, + + event_id_or_alarm_code_value, + + userid_value, + + pin_value + + ) == SL_STATUS_OK) { + return true; + } } -} -// Publishing Cluster Revision for ElectricalConductivityMeasurement Cluster -void uic_mqtt_dotdot_electrical_conductivity_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/ElectricalConductivityMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + return false; } - -// Unretain Cluster Revision for ElectricalConductivityMeasurement Cluster -void uic_mqtt_dotdot_electrical_conductivity_measurement_unretain_cluster_revision(const char* base_topic) +static inline bool uic_mqtt_dotdot_door_lock_set_pin_code_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/ElectricalConductivityMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - + DrlkPINUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkSettableUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + const char* pin_value; + memset(&pin_value, 0x00, sizeof(pin_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_pin_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value, + + user_status_value, + + user_type_value, + + pin_value + + ) == SL_STATUS_OK) { + return true; + } + } -static inline bool uic_mqtt_dotdot_electrical_conductivity_measurement_write_attributes_is_supported( + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_pin_code_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_electrical_conductivity_measurement_write_attributes_callback) { - uic_mqtt_dotdot_electrical_conductivity_measurement_state_t electrical_conductivity_measurement_new_state = {}; - uic_mqtt_dotdot_electrical_conductivity_measurement_updated_state_t electrical_conductivity_measurement_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - electrical_conductivity_measurement_new_state, - electrical_conductivity_measurement_new_updated_state - ) == SL_STATUS_OK) { + DrlkSetCodeStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_pin_code_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_electrical_conductivity_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_pin_code_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_electrical_conductivity_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_electrical_conductivity_measurement_updated_state_t electrical_conductivity_measurement_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - electrical_conductivity_measurement_force_update - ) == SL_STATUS_OK) { + DrlkPINUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_pin_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for ElectricalConductivityMeasurement Cluster -void uic_mqtt_dotdot_electrical_conductivity_measurement_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_get_pin_code_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_electrical_conductivity_measurement_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + const char* code_value; + memset(&code_value, 0x00, sizeof(code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_pin_code_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value, + + user_status_value, + + user_type_value, + + code_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_electrical_conductivity_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_clear_pin_code_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkPINUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_pin_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ElectricalConductivityMeasurement/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/ElectricalConductivityMeasurement/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_clear_pin_code_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_pin_code_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } } -} -// Publishing empty/no Supported Commands for ElectricalConductivityMeasurement Cluster -void uic_mqtt_dotdot_electrical_conductivity_measurement_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ElectricalConductivityMeasurement/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } -} - -// Publishing Cluster Revision for WindSpeedMeasurement Cluster -void uic_mqtt_dotdot_wind_speed_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/WindSpeedMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for WindSpeedMeasurement Cluster -void uic_mqtt_dotdot_wind_speed_measurement_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/WindSpeedMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_wind_speed_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_all_pin_codes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_wind_speed_measurement_write_attributes_callback) { - uic_mqtt_dotdot_wind_speed_measurement_state_t wind_speed_measurement_new_state = {}; - uic_mqtt_dotdot_wind_speed_measurement_updated_state_t wind_speed_measurement_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - wind_speed_measurement_new_state, - wind_speed_measurement_new_updated_state - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_pin_codes_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_wind_speed_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_all_pin_codes_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_wind_speed_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_wind_speed_measurement_updated_state_t wind_speed_measurement_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - wind_speed_measurement_force_update - ) == SL_STATUS_OK) { + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_pin_codes_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for WindSpeedMeasurement Cluster -void uic_mqtt_dotdot_wind_speed_measurement_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_set_user_status_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_wind_speed_measurement_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_wind_speed_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; - } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/WindSpeedMeasurement/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/WindSpeedMeasurement/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkSettableUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_status_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value, + + user_status_value + + ) == SL_STATUS_OK) { + return true; } } -} - -// Publishing empty/no Supported Commands for WindSpeedMeasurement Cluster -void uic_mqtt_dotdot_wind_speed_measurement_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/WindSpeedMeasurement/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } -} - -// Publishing Cluster Revision for CarbonMonoxide Cluster -void uic_mqtt_dotdot_carbon_monoxide_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/CarbonMonoxide/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for CarbonMonoxide Cluster -void uic_mqtt_dotdot_carbon_monoxide_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/CarbonMonoxide/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_carbon_monoxide_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_set_user_status_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_carbon_monoxide_write_attributes_callback) { - uic_mqtt_dotdot_carbon_monoxide_state_t carbon_monoxide_new_state = {}; - uic_mqtt_dotdot_carbon_monoxide_updated_state_t carbon_monoxide_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - carbon_monoxide_new_state, - carbon_monoxide_new_updated_state - ) == SL_STATUS_OK) { + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_status_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_carbon_monoxide_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_user_status_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_carbon_monoxide_force_read_attributes_callback) { - uic_mqtt_dotdot_carbon_monoxide_updated_state_t carbon_monoxide_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - carbon_monoxide_force_update - ) == SL_STATUS_OK) { + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_status_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for CarbonMonoxide Cluster -void uic_mqtt_dotdot_carbon_monoxide_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_get_user_status_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_carbon_monoxide_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_status_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value, + + user_status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_carbon_monoxide_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_weekday_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkWeekDayScheduleID scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + uint8_t days_mask_value; + memset(&days_mask_value, 0x00, sizeof(days_mask_value)); + uint8_t start_hour_value; + memset(&start_hour_value, 0x00, sizeof(start_hour_value)); + uint8_t start_minute_value; + memset(&start_minute_value, 0x00, sizeof(start_minute_value)); + uint8_t end_hour_value; + memset(&end_hour_value, 0x00, sizeof(end_hour_value)); + uint8_t end_minute_value; + memset(&end_minute_value, 0x00, sizeof(end_minute_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_weekday_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value, + + days_mask_value, + + start_hour_value, + + start_minute_value, + + end_hour_value, + + end_minute_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/CarbonMonoxide/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/CarbonMonoxide/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for CarbonMonoxide Cluster -void uic_mqtt_dotdot_carbon_monoxide_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_set_weekday_schedule_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/CarbonMonoxide/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_weekday_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; + } } -} -// Publishing Cluster Revision for CarbonDioxide Cluster -void uic_mqtt_dotdot_carbon_dioxide_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/CarbonDioxide/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + return false; } - -// Unretain Cluster Revision for CarbonDioxide Cluster -void uic_mqtt_dotdot_carbon_dioxide_unretain_cluster_revision(const char* base_topic) +static inline bool uic_mqtt_dotdot_door_lock_get_weekday_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/CarbonDioxide/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - + DrlkWeekDayScheduleID scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_weekday_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value + + ) == SL_STATUS_OK) { + return true; + } + } -static inline bool uic_mqtt_dotdot_carbon_dioxide_write_attributes_is_supported( + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_get_weekday_schedule_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_carbon_dioxide_write_attributes_callback) { - uic_mqtt_dotdot_carbon_dioxide_state_t carbon_dioxide_new_state = {}; - uic_mqtt_dotdot_carbon_dioxide_updated_state_t carbon_dioxide_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - carbon_dioxide_new_state, - carbon_dioxide_new_updated_state - ) == SL_STATUS_OK) { + uint8_t scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint8_t days_mask_value; + memset(&days_mask_value, 0x00, sizeof(days_mask_value)); + uint8_t start_hour_value; + memset(&start_hour_value, 0x00, sizeof(start_hour_value)); + uint8_t start_minute_value; + memset(&start_minute_value, 0x00, sizeof(start_minute_value)); + uint8_t end_hour_value; + memset(&end_hour_value, 0x00, sizeof(end_hour_value)); + uint8_t end_minute_value; + memset(&end_minute_value, 0x00, sizeof(end_minute_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_weekday_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value, + + status_value, + + days_mask_value, + + start_hour_value, + + start_minute_value, + + end_hour_value, + + end_minute_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_carbon_dioxide_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_weekday_schedule_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_carbon_dioxide_force_read_attributes_callback) { - uic_mqtt_dotdot_carbon_dioxide_updated_state_t carbon_dioxide_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - carbon_dioxide_force_update - ) == SL_STATUS_OK) { + DrlkWeekDayScheduleID scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_weekday_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for CarbonDioxide Cluster -void uic_mqtt_dotdot_carbon_dioxide_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_clear_weekday_schedule_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_carbon_dioxide_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_weekday_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_carbon_dioxide_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_year_day_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkYearDayScheduleID scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + uint32_t local_start_time_value; + memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); + uint32_t local_end_time_value; + memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_year_day_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value, + + local_start_time_value, + + local_end_time_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/CarbonDioxide/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/CarbonDioxide/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for CarbonDioxide Cluster -void uic_mqtt_dotdot_carbon_dioxide_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_set_year_day_schedule_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/CarbonDioxide/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_year_day_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; + } } -} - -// Publishing Cluster Revision for PM25 Cluster -void uic_mqtt_dotdot_pm25_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/PM25/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for PM25 Cluster -void uic_mqtt_dotdot_pm25_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/PM25/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_pm25_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_year_day_schedule_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_pm25_write_attributes_callback) { - uic_mqtt_dotdot_pm25_state_t pm25_new_state = {}; - uic_mqtt_dotdot_pm25_updated_state_t pm25_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - pm25_new_state, - pm25_new_updated_state - ) == SL_STATUS_OK) { + DrlkYearDayScheduleID scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_year_day_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_pm25_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_year_day_schedule_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_pm25_force_read_attributes_callback) { - uic_mqtt_dotdot_pm25_updated_state_t pm25_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - pm25_force_update - ) == SL_STATUS_OK) { + uint8_t scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint32_t local_start_time_value; + memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); + uint32_t local_end_time_value; + memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_year_day_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value, + + status_value, + + local_start_time_value, + + local_end_time_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for PM25 Cluster -void uic_mqtt_dotdot_pm25_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_clear_year_day_schedule_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_pm25_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + DrlkYearDayScheduleID scheduleid_value; + memset(&scheduleid_value, 0x00, sizeof(scheduleid_value)); + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_year_day_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + scheduleid_value, + + userid_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_pm25_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_clear_year_day_schedule_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_year_day_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PM25/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/PM25/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for PM25 Cluster -void uic_mqtt_dotdot_pm25_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_set_holiday_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/PM25/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + DrlkHolidayScheduleID holiday_scheduleid_value; + memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); + uint32_t local_start_time_value; + memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); + uint32_t local_end_time_value; + memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); + DrlkOperMode operating_mode_during_holiday_value; + memset(&operating_mode_during_holiday_value, 0x00, sizeof(operating_mode_during_holiday_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_holiday_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + holiday_scheduleid_value, + + local_start_time_value, + + local_end_time_value, + + operating_mode_during_holiday_value + + ) == SL_STATUS_OK) { + return true; + } } -} -// Publishing Cluster Revision for IASZone Cluster -void uic_mqtt_dotdot_ias_zone_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/IASZone/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); + return false; } - -// Unretain Cluster Revision for IASZone Cluster -void uic_mqtt_dotdot_ias_zone_unretain_cluster_revision(const char* base_topic) +static inline bool uic_mqtt_dotdot_door_lock_set_holiday_schedule_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/IASZone/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_holiday_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; + } + } -static inline bool uic_mqtt_dotdot_ias_zone_zone_enroll_response_is_supported( + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_get_holiday_schedule_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - ZoneEnrollResponseEnrollResponseCode enroll_response_code_value; - memset(&enroll_response_code_value, 0x00, sizeof(enroll_response_code_value)); - uint8_t zoneid_value; - memset(&zoneid_value, 0x00, sizeof(zoneid_value)); - for (const auto& callback: uic_mqtt_dotdot_ias_zone_zone_enroll_response_callback) { + DrlkHolidayScheduleID holiday_scheduleid_value; + memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_holiday_schedule_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - enroll_response_code_value, - - zoneid_value + holiday_scheduleid_value ) == SL_STATUS_OK) { return true; @@ -108364,28 +106778,32 @@ static inline bool uic_mqtt_dotdot_ias_zone_zone_enroll_response_is_supported( return false; } -static inline bool uic_mqtt_dotdot_ias_zone_zone_status_change_notification_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_holiday_schedule_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t zone_status_value; - memset(&zone_status_value, 0x00, sizeof(zone_status_value)); - uint8_t extended_status_value; - memset(&extended_status_value, 0x00, sizeof(extended_status_value)); - uint8_t zoneid_value; - memset(&zoneid_value, 0x00, sizeof(zoneid_value)); - uint16_t delay_value; - memset(&delay_value, 0x00, sizeof(delay_value)); - for (const auto& callback: uic_mqtt_dotdot_ias_zone_zone_status_change_notification_callback) { + uint8_t holiday_scheduleid_value; + memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); + zclStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + uint32_t local_start_time_value; + memset(&local_start_time_value, 0x00, sizeof(local_start_time_value)); + uint32_t local_end_time_value; + memset(&local_end_time_value, 0x00, sizeof(local_end_time_value)); + DrlkOperMode operating_mode_during_holiday_value; + memset(&operating_mode_during_holiday_value, 0x00, sizeof(operating_mode_during_holiday_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_holiday_schedule_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - zone_status_value, + holiday_scheduleid_value, - extended_status_value, + status_value, - zoneid_value, + local_start_time_value, - delay_value + local_end_time_value, + + operating_mode_during_holiday_value ) == SL_STATUS_OK) { return true; @@ -108394,12 +106812,16 @@ static inline bool uic_mqtt_dotdot_ias_zone_zone_status_change_notification_is_s return false; } -static inline bool uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_holiday_schedule_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_callback) { + DrlkHolidayScheduleID holiday_scheduleid_value; + memset(&holiday_scheduleid_value, 0x00, sizeof(holiday_scheduleid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_holiday_schedule_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + holiday_scheduleid_value ) == SL_STATUS_OK) { return true; @@ -108408,20 +106830,16 @@ static inline bool uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_is_su return false; } -static inline bool uic_mqtt_dotdot_ias_zone_zone_enroll_request_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_holiday_schedule_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - IasZoneType zone_type_value; - memset(&zone_type_value, 0x00, sizeof(zone_type_value)); - uint16_t manufacturer_code_value; - memset(&manufacturer_code_value, 0x00, sizeof(manufacturer_code_value)); - for (const auto& callback: uic_mqtt_dotdot_ias_zone_zone_enroll_request_callback) { + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_holiday_schedule_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - zone_type_value, - - manufacturer_code_value + status_value ) == SL_STATUS_OK) { return true; @@ -108430,20 +106848,20 @@ static inline bool uic_mqtt_dotdot_ias_zone_zone_enroll_request_is_supported( return false; } -static inline bool uic_mqtt_dotdot_ias_zone_initiate_test_mode_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_set_user_type_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t test_mode_duration_value; - memset(&test_mode_duration_value, 0x00, sizeof(test_mode_duration_value)); - uint8_t current_zone_sensitivity_level_value; - memset(¤t_zone_sensitivity_level_value, 0x00, sizeof(current_zone_sensitivity_level_value)); - for (const auto& callback: uic_mqtt_dotdot_ias_zone_initiate_test_mode_callback) { + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_type_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - test_mode_duration_value, + userid_value, - current_zone_sensitivity_level_value + user_type_value ) == SL_STATUS_OK) { return true; @@ -108452,211 +106870,152 @@ static inline bool uic_mqtt_dotdot_ias_zone_initiate_test_mode_is_supported( return false; } - -static inline bool uic_mqtt_dotdot_ias_zone_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_set_user_type_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ias_zone_write_attributes_callback) { - uic_mqtt_dotdot_ias_zone_state_t ias_zone_new_state = {}; - uic_mqtt_dotdot_ias_zone_updated_state_t ias_zone_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - ias_zone_new_state, - ias_zone_new_updated_state - ) == SL_STATUS_OK) { + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_type_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_ias_zone_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_user_type_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_ias_zone_force_read_attributes_callback) { - uic_mqtt_dotdot_ias_zone_updated_state_t ias_zone_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - ias_zone_force_update - ) == SL_STATUS_OK) { + DrlkTotalUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_type_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for IASZone Cluster -void uic_mqtt_dotdot_ias_zone_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_get_user_type_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_ias_zone_zone_enroll_response_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ZoneEnrollResponse")"; - } - if (uic_mqtt_dotdot_ias_zone_zone_status_change_notification_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ZoneStatusChangeNotification")"; - } - if (uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("InitiateNormalOperationMode")"; - } - if (uic_mqtt_dotdot_ias_zone_zone_enroll_request_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ZoneEnrollRequest")"; - } - if (uic_mqtt_dotdot_ias_zone_initiate_test_mode_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_type_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value, + + user_type_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("InitiateTestMode")"; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_ias_zone_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_rfid_code_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkRFIDUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkSettableUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + const char* rfid_code_value; + memset(&rfid_code_value, 0x00, sizeof(rfid_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_rfid_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value, + + user_status_value, + + user_type_value, + + rfid_code_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_ias_zone_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_rfid_code_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DrlkSetCodeStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_rfid_code_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IASZone/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/IASZone/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for IASZone Cluster -void uic_mqtt_dotdot_ias_zone_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_get_rfid_code_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IASZone/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + DrlkRFIDUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_rfid_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + userid_value + + ) == SL_STATUS_OK) { + return true; + } } -} - -// Publishing Cluster Revision for IASWD Cluster -void uic_mqtt_dotdot_iaswd_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/IASWD/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for IASWD Cluster -void uic_mqtt_dotdot_iaswd_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/IASWD/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - -static inline bool uic_mqtt_dotdot_iaswd_start_warning_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_rfid_code_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t siren_configuration_value; - memset(&siren_configuration_value, 0x00, sizeof(siren_configuration_value)); - uint16_t warning_duration_value; - memset(&warning_duration_value, 0x00, sizeof(warning_duration_value)); - uint8_t strobe_duty_cycle_value; - memset(&strobe_duty_cycle_value, 0x00, sizeof(strobe_duty_cycle_value)); - IaswdLevel strobe_level_value; - memset(&strobe_level_value, 0x00, sizeof(strobe_level_value)); - for (const auto& callback: uic_mqtt_dotdot_iaswd_start_warning_callback) { + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + DrlkUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + const char* rfid_code_value; + memset(&rfid_code_value, 0x00, sizeof(rfid_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_rfid_code_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - siren_configuration_value, + userid_value, - warning_duration_value, + user_status_value, - strobe_duty_cycle_value, + user_type_value, - strobe_level_value + rfid_code_value ) == SL_STATUS_OK) { return true; @@ -108665,16 +107024,16 @@ static inline bool uic_mqtt_dotdot_iaswd_start_warning_is_supported( return false; } -static inline bool uic_mqtt_dotdot_iaswd_squawk_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_rfid_code_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t squawk_configuration_value; - memset(&squawk_configuration_value, 0x00, sizeof(squawk_configuration_value)); - for (const auto& callback: uic_mqtt_dotdot_iaswd_squawk_callback) { + DrlkRFIDUserID userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_rfid_code_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - squawk_configuration_value + userid_value ) == SL_STATUS_OK) { return true; @@ -108683,337 +107042,295 @@ static inline bool uic_mqtt_dotdot_iaswd_squawk_is_supported( return false; } - -static inline bool uic_mqtt_dotdot_iaswd_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_rfid_code_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_iaswd_write_attributes_callback) { - uic_mqtt_dotdot_iaswd_state_t iaswd_new_state = {}; - uic_mqtt_dotdot_iaswd_updated_state_t iaswd_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - iaswd_new_state, - iaswd_new_updated_state - ) == SL_STATUS_OK) { + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_rfid_code_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_iaswd_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_iaswd_force_read_attributes_callback) { - uic_mqtt_dotdot_iaswd_updated_state_t iaswd_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - iaswd_force_update - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for IASWD Cluster -void uic_mqtt_dotdot_iaswd_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_iaswd_start_warning_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("StartWarning")"; - } - if (uic_mqtt_dotdot_iaswd_squawk_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + DrlkPassFailStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + status_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("Squawk")"; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_iaswd_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_user_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DataOperationTypeEnum operation_type_value; + memset(&operation_type_value, 0x00, sizeof(operation_type_value)); + uint16_t user_index_value; + memset(&user_index_value, 0x00, sizeof(user_index_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint32_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + DrlkSettableUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + CredentialRuleEnum credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + operation_type_value, + + user_index_value, + + user_name_value, + + user_uniqueid_value, + + user_status_value, + + user_type_value, + + credential_rule_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_iaswd_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_get_user_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_index_value; + memset(&user_index_value, 0x00, sizeof(user_index_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_index_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IASWD/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/IASWD/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for IASWD Cluster -void uic_mqtt_dotdot_iaswd_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_get_user_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/IASWD/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_user_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } } -} - -// Publishing Cluster Revision for Metering Cluster -void uic_mqtt_dotdot_metering_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Metering/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for Metering Cluster -void uic_mqtt_dotdot_metering_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Metering/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - - -static inline bool uic_mqtt_dotdot_metering_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_user_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_metering_write_attributes_callback) { - uic_mqtt_dotdot_metering_state_t metering_new_state = {}; - uic_mqtt_dotdot_metering_updated_state_t metering_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - metering_new_state, - metering_new_updated_state - ) == SL_STATUS_OK) { + uint16_t user_index_value; + memset(&user_index_value, 0x00, sizeof(user_index_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_index_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_metering_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_operating_event_notification_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_metering_force_read_attributes_callback) { - uic_mqtt_dotdot_metering_updated_state_t metering_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - metering_force_update - ) == SL_STATUS_OK) { + DrlkOperEventSource operation_event_source_value; + memset(&operation_event_source_value, 0x00, sizeof(operation_event_source_value)); + OperatingEventNotificationOperationEventCode operation_event_code_value; + memset(&operation_event_code_value, 0x00, sizeof(operation_event_code_value)); + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + const char* pin_value; + memset(&pin_value, 0x00, sizeof(pin_value)); + uint32_t local_time_value; + memset(&local_time_value, 0x00, sizeof(local_time_value)); + const char* data_value; + memset(&data_value, 0x00, sizeof(data_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_operating_event_notification_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + operation_event_source_value, + + operation_event_code_value, + + userid_value, + + pin_value, + + local_time_value, + + data_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for Metering Cluster -void uic_mqtt_dotdot_metering_publish_supported_commands( +static inline bool uic_mqtt_dotdot_door_lock_programming_event_notification_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_metering_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + ProgrammingEventNotificationProgramEventSource program_event_source_value; + memset(&program_event_source_value, 0x00, sizeof(program_event_source_value)); + ProgrammingEventNotificationProgramEventCode program_event_code_value; + memset(&program_event_code_value, 0x00, sizeof(program_event_code_value)); + uint16_t userid_value; + memset(&userid_value, 0x00, sizeof(userid_value)); + const char* pin_value; + memset(&pin_value, 0x00, sizeof(pin_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + DrlkUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + uint32_t local_time_value; + memset(&local_time_value, 0x00, sizeof(local_time_value)); + const char* data_value; + memset(&data_value, 0x00, sizeof(data_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_programming_event_notification_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + program_event_source_value, + + program_event_code_value, + + userid_value, + + pin_value, + + user_type_value, + + user_status_value, + + local_time_value, + + data_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_metering_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_door_lock_set_credential_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + DataOperationTypeEnum operation_type_value; + memset(&operation_type_value, 0x00, sizeof(operation_type_value)); + CredentialStruct credential_value; + memset(&credential_value, 0x00, sizeof(credential_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + uint16_t user_index_value; + memset(&user_index_value, 0x00, sizeof(user_index_value)); + DrlkSettableUserStatus user_status_value; + memset(&user_status_value, 0x00, sizeof(user_status_value)); + DrlkUserType user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_credential_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + operation_type_value, + + credential_value, + + credential_data_value, + + user_index_value, + + user_status_value, + + user_type_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Metering/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Metering/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for Metering Cluster -void uic_mqtt_dotdot_metering_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_door_lock_set_credential_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Metering/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + for (const auto& callback: uic_mqtt_dotdot_door_lock_set_credential_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } } -} - -// Publishing Cluster Revision for ElectricalMeasurement Cluster -void uic_mqtt_dotdot_electrical_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/ElectricalMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for ElectricalMeasurement Cluster -void uic_mqtt_dotdot_electrical_measurement_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/ElectricalMeasurement/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - -static inline bool uic_mqtt_dotdot_electrical_measurement_get_profile_info_response_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_credential_status_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint8_t profile_count_value; - memset(&profile_count_value, 0x00, sizeof(profile_count_value)); - ProfileIntervalPeriod profile_interval_period_value; - memset(&profile_interval_period_value, 0x00, sizeof(profile_interval_period_value)); - uint8_t max_number_of_intervals_value; - memset(&max_number_of_intervals_value, 0x00, sizeof(max_number_of_intervals_value)); - for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_profile_info_response_callback) { + CredentialStruct credential_value; + memset(&credential_value, 0x00, sizeof(credential_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_credential_status_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - profile_count_value, - - profile_interval_period_value, - - max_number_of_intervals_value, + credential_value - 0, nullptr - ) == SL_STATUS_OK) { return true; } @@ -109021,11 +107338,11 @@ static inline bool uic_mqtt_dotdot_electrical_measurement_get_profile_info_respo return false; } -static inline bool uic_mqtt_dotdot_electrical_measurement_get_profile_info_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_get_credential_status_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_profile_info_callback) { + for (const auto& callback: uic_mqtt_dotdot_door_lock_get_credential_status_response_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK ) == SL_STATUS_OK) { @@ -109035,35 +107352,17 @@ static inline bool uic_mqtt_dotdot_electrical_measurement_get_profile_info_is_su return false; } -static inline bool uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_response_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_clear_credential_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - UTC start_time_value; - memset(&start_time_value, 0x00, sizeof(start_time_value)); - GetMeasurementProfileResponseStatus status_value; - memset(&status_value, 0x00, sizeof(status_value)); - ProfileIntervalPeriod profile_interval_period_value; - memset(&profile_interval_period_value, 0x00, sizeof(profile_interval_period_value)); - uint8_t number_of_intervals_delivered_value; - memset(&number_of_intervals_delivered_value, 0x00, sizeof(number_of_intervals_delivered_value)); - uint16_t attribute_id_value; - memset(&attribute_id_value, 0x00, sizeof(attribute_id_value)); - for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_response_callback) { + CredentialStruct credential_value; + memset(&credential_value, 0x00, sizeof(credential_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_clear_credential_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - start_time_value, - - status_value, - - profile_interval_period_value, - - number_of_intervals_delivered_value, - - attribute_id_value, + credential_value - 0, nullptr - ) == SL_STATUS_OK) { return true; } @@ -109071,24 +107370,16 @@ static inline bool uic_mqtt_dotdot_electrical_measurement_get_measurement_profil return false; } -static inline bool uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_unbolt_door_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t attributeid_value; - memset(&attributeid_value, 0x00, sizeof(attributeid_value)); - UTC start_time_value; - memset(&start_time_value, 0x00, sizeof(start_time_value)); - uint8_t number_of_intervals_value; - memset(&number_of_intervals_value, 0x00, sizeof(number_of_intervals_value)); - for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_callback) { + const char* pin_code_value; + memset(&pin_code_value, 0x00, sizeof(pin_code_value)); + for (const auto& callback: uic_mqtt_dotdot_door_lock_unbolt_door_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - attributeid_value, - - start_time_value, - - number_of_intervals_value + pin_code_value ) == SL_STATUS_OK) { return true; @@ -109098,20 +107389,20 @@ static inline bool uic_mqtt_dotdot_electrical_measurement_get_measurement_profil return false; } -static inline bool uic_mqtt_dotdot_electrical_measurement_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_write_attributes_callback) { - uic_mqtt_dotdot_electrical_measurement_state_t electrical_measurement_new_state = {}; - uic_mqtt_dotdot_electrical_measurement_updated_state_t electrical_measurement_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_door_lock_write_attributes_callback) { + uic_mqtt_dotdot_door_lock_state_t door_lock_new_state = {}; + uic_mqtt_dotdot_door_lock_updated_state_t door_lock_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - electrical_measurement_new_state, - electrical_measurement_new_updated_state + door_lock_new_state, + door_lock_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -109119,17 +107410,17 @@ static inline bool uic_mqtt_dotdot_electrical_measurement_write_attributes_is_su return false; } -static inline bool uic_mqtt_dotdot_electrical_measurement_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_door_lock_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_force_read_attributes_callback) { - uic_mqtt_dotdot_electrical_measurement_updated_state_t electrical_measurement_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_door_lock_force_read_attributes_callback) { + uic_mqtt_dotdot_door_lock_updated_state_t door_lock_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - electrical_measurement_force_update + door_lock_force_update ) == SL_STATUS_OK) { return true; } @@ -109137,8 +107428,8 @@ static inline bool uic_mqtt_dotdot_electrical_measurement_force_read_attributes_ return false; } -// Publishing Supported Commands for ElectricalMeasurement Cluster -void uic_mqtt_dotdot_electrical_measurement_publish_supported_commands( +// Publishing Supported Commands for DoorLock Cluster +void uic_mqtt_dotdot_door_lock_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -109147,1089 +107438,457 @@ void uic_mqtt_dotdot_electrical_measurement_publish_supported_commands( ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_electrical_measurement_get_profile_info_response_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_lock_door_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetProfileInfoResponse")"; + ss << R"("LockDoor")"; } - if (uic_mqtt_dotdot_electrical_measurement_get_profile_info_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_lock_door_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetProfileInfo")"; + ss << R"("LockDoorResponse")"; } - if (uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_response_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_unlock_door_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetMeasurementProfileResponse")"; + ss << R"("UnlockDoor")"; } - if (uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_unlock_door_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("GetMeasurementProfile")"; + ss << R"("UnlockDoorResponse")"; } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_electrical_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_toggle_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("Toggle")"; } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_electrical_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_toggle_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("ToggleResponse")"; } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ElectricalMeasurement/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/ElectricalMeasurement/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_unlock_with_timeout_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("UnlockWithTimeout")"; } -} - -// Publishing empty/no Supported Commands for ElectricalMeasurement Cluster -void uic_mqtt_dotdot_electrical_measurement_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ElectricalMeasurement/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_unlock_with_timeout_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("UnlockWithTimeoutResponse")"; } -} - -// Publishing Cluster Revision for Diagnostics Cluster -void uic_mqtt_dotdot_diagnostics_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Diagnostics/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for Diagnostics Cluster -void uic_mqtt_dotdot_diagnostics_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Diagnostics/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - - -static inline bool uic_mqtt_dotdot_diagnostics_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_diagnostics_write_attributes_callback) { - uic_mqtt_dotdot_diagnostics_state_t diagnostics_new_state = {}; - uic_mqtt_dotdot_diagnostics_updated_state_t diagnostics_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - diagnostics_new_state, - diagnostics_new_updated_state - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_log_record_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetLogRecord")"; } - return false; -} - -static inline bool uic_mqtt_dotdot_diagnostics_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_diagnostics_force_read_attributes_callback) { - uic_mqtt_dotdot_diagnostics_updated_state_t diagnostics_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - diagnostics_force_update - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_log_record_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetLogRecordResponse")"; } - return false; -} - -// Publishing Supported Commands for Diagnostics Cluster -void uic_mqtt_dotdot_diagnostics_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_diagnostics_write_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_pin_code_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("SetPINCode")"; } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_diagnostics_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_pin_code_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("SetPINCodeResponse")"; } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Diagnostics/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Diagnostics/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_get_pin_code_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetPINCode")"; } -} - -// Publishing empty/no Supported Commands for Diagnostics Cluster -void uic_mqtt_dotdot_diagnostics_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Diagnostics/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_get_pin_code_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetPINCodeResponse")"; } -} - -// Publishing Cluster Revision for ProtocolController-RFTelemetry Cluster -void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/ProtocolController/RFTelemetry/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for ProtocolController-RFTelemetry Cluster -void uic_mqtt_dotdot_protocol_controller_rf_telemetry_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/ProtocolController/RFTelemetry/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - -static inline bool uic_mqtt_dotdot_protocol_controller_rf_telemetry_tx_report_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* sourceunid_value; - memset(&sourceunid_value, 0x00, sizeof(sourceunid_value)); - const char* destinationunid_value; - memset(&destinationunid_value, 0x00, sizeof(destinationunid_value)); - bool transmission_successful_value; - memset(&transmission_successful_value, 0x00, sizeof(transmission_successful_value)); - uint16_t transmission_time_ms_value; - memset(&transmission_time_ms_value, 0x00, sizeof(transmission_time_ms_value)); - int8_t tx_powerd_bm_value; - memset(&tx_powerd_bm_value, 0x00, sizeof(tx_powerd_bm_value)); - uint8_t tx_channel_value; - memset(&tx_channel_value, 0x00, sizeof(tx_channel_value)); - uint8_t routing_attempts_value; - memset(&routing_attempts_value, 0x00, sizeof(routing_attempts_value)); - bool route_changed_value; - memset(&route_changed_value, 0x00, sizeof(route_changed_value)); - TxReportTransmissionSpeed transmission_speed_value; - memset(&transmission_speed_value, 0x00, sizeof(transmission_speed_value)); - int8_t measured_noise_floord_bm_value; - memset(&measured_noise_floord_bm_value, 0x00, sizeof(measured_noise_floord_bm_value)); - int8_t ackrssi_value; - memset(&ackrssi_value, 0x00, sizeof(ackrssi_value)); - uint8_t ack_channel_value; - memset(&ack_channel_value, 0x00, sizeof(ack_channel_value)); - const char* last_route_failed_link_functionalunid_value; - memset(&last_route_failed_link_functionalunid_value, 0x00, sizeof(last_route_failed_link_functionalunid_value)); - const char* last_route_failed_link_non_functionalunid_value; - memset(&last_route_failed_link_non_functionalunid_value, 0x00, sizeof(last_route_failed_link_non_functionalunid_value)); - int8_t destination_ack_tx_powerd_bm_value; - memset(&destination_ack_tx_powerd_bm_value, 0x00, sizeof(destination_ack_tx_powerd_bm_value)); - int8_t destination_ack_measuredrssi_value; - memset(&destination_ack_measuredrssi_value, 0x00, sizeof(destination_ack_measuredrssi_value)); - int8_t destination_ack_measured_noise_floor_value; - memset(&destination_ack_measured_noise_floor_value, 0x00, sizeof(destination_ack_measured_noise_floor_value)); - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_rf_telemetry_tx_report_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - sourceunid_value, - - destinationunid_value, - - transmission_successful_value, - - transmission_time_ms_value, - - tx_powerd_bm_value, - - tx_channel_value, - - routing_attempts_value, - - route_changed_value, - - transmission_speed_value, - - measured_noise_floord_bm_value, - - 0, nullptr, - - 0, nullptr, - - ackrssi_value, - - ack_channel_value, - - last_route_failed_link_functionalunid_value, - - last_route_failed_link_non_functionalunid_value, - - destination_ack_tx_powerd_bm_value, - - destination_ack_measuredrssi_value, - - destination_ack_measured_noise_floor_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_pin_code_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearPINCode")"; } - - return false; -} - -static inline bool uic_mqtt_dotdot_protocol_controller_rf_telemetry_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_rf_telemetry_write_attributes_callback) { - uic_mqtt_dotdot_protocol_controller_rf_telemetry_state_t protocol_controller_rf_telemetry_new_state = {}; - uic_mqtt_dotdot_protocol_controller_rf_telemetry_updated_state_t protocol_controller_rf_telemetry_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - protocol_controller_rf_telemetry_new_state, - protocol_controller_rf_telemetry_new_updated_state - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_pin_code_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearPINCodeResponse")"; } - return false; -} - -static inline bool uic_mqtt_dotdot_protocol_controller_rf_telemetry_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_rf_telemetry_force_read_attributes_callback) { - uic_mqtt_dotdot_protocol_controller_rf_telemetry_updated_state_t protocol_controller_rf_telemetry_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - protocol_controller_rf_telemetry_force_update - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_all_pin_codes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearAllPINCodes")"; } - return false; -} - -// Publishing Supported Commands for ProtocolController-RFTelemetry Cluster -void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_protocol_controller_rf_telemetry_tx_report_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_clear_all_pin_codes_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("TxReport")"; + ss << R"("ClearAllPINCodesResponse")"; } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_protocol_controller_rf_telemetry_write_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_user_status_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("SetUserStatus")"; } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_protocol_controller_rf_telemetry_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_user_status_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("SetUserStatusResponse")"; } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - - topic += "/ProtocolController/RFTelemetry/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - - attributes_topic += "/ProtocolController/RFTelemetry/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_get_user_status_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetUserStatus")"; } -} - -// Publishing empty/no Supported Commands for ProtocolController-RFTelemetry Cluster -void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_empty_supported_commands( - const dotdot_unid_t unid - ) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ProtocolController/RFTelemetry/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_get_user_status_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetUserStatusResponse")"; } -} - -// Publishing Cluster Revision for State Cluster -void uic_mqtt_dotdot_state_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/State/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for State Cluster -void uic_mqtt_dotdot_state_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/State/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - -static inline bool uic_mqtt_dotdot_state_remove_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_remove_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_set_weekday_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("SetWeekdaySchedule")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_state_remove_offline_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_remove_offline_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_set_weekday_schedule_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("SetWeekdayScheduleResponse")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_state_discover_neighbors_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_discover_neighbors_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_weekday_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetWeekdaySchedule")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_state_interview_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_interview_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_weekday_schedule_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetWeekdayScheduleResponse")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_state_discover_security_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_discover_security_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_weekday_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearWeekdaySchedule")"; } - - return false; -} - -static inline bool uic_mqtt_dotdot_state_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_write_attributes_callback) { - uic_mqtt_dotdot_state_state_t state_new_state = {}; - uic_mqtt_dotdot_state_updated_state_t state_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - state_new_state, - state_new_updated_state - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_weekday_schedule_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearWeekdayScheduleResponse")"; } - return false; -} - -static inline bool uic_mqtt_dotdot_state_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_state_force_read_attributes_callback) { - uic_mqtt_dotdot_state_updated_state_t state_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - state_force_update - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_set_year_day_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("SetYearDaySchedule")"; } - return false; -} - -// Publishing Supported Commands for State Cluster -void uic_mqtt_dotdot_state_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_state_remove_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_year_day_schedule_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("Remove")"; + ss << R"("SetYearDayScheduleResponse")"; } - if (uic_mqtt_dotdot_state_remove_offline_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_get_year_day_schedule_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("RemoveOffline")"; + ss << R"("GetYearDaySchedule")"; } - if (uic_mqtt_dotdot_state_discover_neighbors_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_get_year_day_schedule_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("DiscoverNeighbors")"; + ss << R"("GetYearDayScheduleResponse")"; } - if (uic_mqtt_dotdot_state_interview_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_clear_year_day_schedule_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("Interview")"; + ss << R"("ClearYearDaySchedule")"; } - if (uic_mqtt_dotdot_state_discover_security_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_clear_year_day_schedule_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("DiscoverSecurity")"; + ss << R"("ClearYearDayScheduleResponse")"; } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_state_write_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_holiday_schedule_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("SetHolidaySchedule")"; } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_state_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_holiday_schedule_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("SetHolidayScheduleResponse")"; } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - - topic += "/State/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - - attributes_topic += "/State/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_get_holiday_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetHolidaySchedule")"; } -} - -// Publishing empty/no Supported Commands for State Cluster -void uic_mqtt_dotdot_state_publish_empty_supported_commands( - const dotdot_unid_t unid - ) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/State/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_get_holiday_schedule_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetHolidayScheduleResponse")"; } -} - -// Publishing Cluster Revision for Binding Cluster -void uic_mqtt_dotdot_binding_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/Binding/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for Binding Cluster -void uic_mqtt_dotdot_binding_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/Binding/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - -static inline bool uic_mqtt_dotdot_binding_bind_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* cluster_name_value; - memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); - const char* destination_unid_value; - memset(&destination_unid_value, 0x00, sizeof(destination_unid_value)); - uint8_t destination_ep_value; - memset(&destination_ep_value, 0x00, sizeof(destination_ep_value)); - for (const auto& callback: uic_mqtt_dotdot_binding_bind_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - cluster_name_value, - - destination_unid_value, - - destination_ep_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_holiday_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearHolidaySchedule")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_binding_unbind_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* cluster_name_value; - memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); - const char* destination_unid_value; - memset(&destination_unid_value, 0x00, sizeof(destination_unid_value)); - uint8_t destination_ep_value; - memset(&destination_ep_value, 0x00, sizeof(destination_ep_value)); - for (const auto& callback: uic_mqtt_dotdot_binding_unbind_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - cluster_name_value, - - destination_unid_value, - - destination_ep_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_clear_holiday_schedule_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearHolidayScheduleResponse")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_binding_bind_to_protocol_controller_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* cluster_name_value; - memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); - for (const auto& callback: uic_mqtt_dotdot_binding_bind_to_protocol_controller_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - cluster_name_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_set_user_type_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("SetUserType")"; } - - return false; -} -static inline bool uic_mqtt_dotdot_binding_unbind_from_protocol_controller_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* cluster_name_value; - memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); - for (const auto& callback: uic_mqtt_dotdot_binding_unbind_from_protocol_controller_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - cluster_name_value - - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_set_user_type_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("SetUserTypeResponse")"; } - - return false; -} - -static inline bool uic_mqtt_dotdot_binding_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_binding_write_attributes_callback) { - uic_mqtt_dotdot_binding_state_t binding_new_state = {}; - uic_mqtt_dotdot_binding_updated_state_t binding_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - binding_new_state, - binding_new_updated_state - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_user_type_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetUserType")"; } - return false; -} - -static inline bool uic_mqtt_dotdot_binding_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_binding_force_read_attributes_callback) { - uic_mqtt_dotdot_binding_updated_state_t binding_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - binding_force_update - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_user_type_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetUserTypeResponse")"; } - return false; -} - -// Publishing Supported Commands for Binding Cluster -void uic_mqtt_dotdot_binding_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_binding_bind_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_rfid_code_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("Bind")"; + ss << R"("SetRFIDCode")"; } - if (uic_mqtt_dotdot_binding_unbind_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_set_rfid_code_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("Unbind")"; + ss << R"("SetRFIDCodeResponse")"; } - if (uic_mqtt_dotdot_binding_bind_to_protocol_controller_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_get_rfid_code_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("BindToProtocolController")"; + ss << R"("GetRFIDCode")"; } - if (uic_mqtt_dotdot_binding_unbind_from_protocol_controller_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_get_rfid_code_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("UnbindFromProtocolController")"; + ss << R"("GetRFIDCodeResponse")"; } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_binding_write_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_clear_rfid_code_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("ClearRFIDCode")"; } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_binding_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_clear_rfid_code_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("ClearRFIDCodeResponse")"; } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Binding/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Binding/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("ClearAllRFIDCodes")"; } -} - -// Publishing empty/no Supported Commands for Binding Cluster -void uic_mqtt_dotdot_binding_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Binding/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + if (uic_mqtt_dotdot_door_lock_clear_all_rfid_codes_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ClearAllRFIDCodesResponse")"; } -} - -// Publishing Cluster Revision for SystemMetrics Cluster -void uic_mqtt_dotdot_system_metrics_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/SystemMetrics/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} - -// Unretain Cluster Revision for SystemMetrics Cluster -void uic_mqtt_dotdot_system_metrics_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/SystemMetrics/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off -} - - -static inline bool uic_mqtt_dotdot_system_metrics_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_system_metrics_write_attributes_callback) { - uic_mqtt_dotdot_system_metrics_state_t system_metrics_new_state = {}; - uic_mqtt_dotdot_system_metrics_updated_state_t system_metrics_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - system_metrics_new_state, - system_metrics_new_updated_state - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_set_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("SetUser")"; } - return false; -} - -static inline bool uic_mqtt_dotdot_system_metrics_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_system_metrics_force_read_attributes_callback) { - uic_mqtt_dotdot_system_metrics_updated_state_t system_metrics_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - system_metrics_force_update - ) == SL_STATUS_OK) { - return true; + if (uic_mqtt_dotdot_door_lock_get_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; } + first_command = false; + ss << R"("GetUser")"; + } + if (uic_mqtt_dotdot_door_lock_get_user_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetUserResponse")"; + } + if (uic_mqtt_dotdot_door_lock_clear_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ClearUser")"; + } + if (uic_mqtt_dotdot_door_lock_operating_event_notification_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("OperatingEventNotification")"; + } + if (uic_mqtt_dotdot_door_lock_programming_event_notification_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ProgrammingEventNotification")"; + } + if (uic_mqtt_dotdot_door_lock_set_credential_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetCredential")"; + } + if (uic_mqtt_dotdot_door_lock_set_credential_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetCredentialResponse")"; + } + if (uic_mqtt_dotdot_door_lock_get_credential_status_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetCredentialStatus")"; + } + if (uic_mqtt_dotdot_door_lock_get_credential_status_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetCredentialStatusResponse")"; + } + if (uic_mqtt_dotdot_door_lock_clear_credential_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ClearCredential")"; + } + if (uic_mqtt_dotdot_door_lock_unbolt_door_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("UnboltDoor")"; } - return false; -} - -// Publishing Supported Commands for SystemMetrics Cluster -void uic_mqtt_dotdot_system_metrics_publish_supported_commands( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_system_metrics_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_door_lock_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -110238,7 +107897,7 @@ void uic_mqtt_dotdot_system_metrics_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_system_metrics_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_door_lock_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -110248,8 +107907,8 @@ void uic_mqtt_dotdot_system_metrics_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); - - topic += "/SystemMetrics/SupportedCommands"; + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/DoorLock/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -110260,8 +107919,8 @@ void uic_mqtt_dotdot_system_metrics_publish_supported_commands( // There are no supported commands, but make sure we publish some // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - - attributes_topic += "/SystemMetrics/Attributes"; + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/DoorLock/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -110272,13 +107931,14 @@ void uic_mqtt_dotdot_system_metrics_publish_supported_commands( } } -// Publishing empty/no Supported Commands for SystemMetrics Cluster -void uic_mqtt_dotdot_system_metrics_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for DoorLock Cluster +void uic_mqtt_dotdot_door_lock_publish_empty_supported_commands( const dotdot_unid_t unid - ) + , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/SystemMetrics/SupportedCommands"; + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/DoorLock/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -110288,10 +107948,10 @@ void uic_mqtt_dotdot_system_metrics_publish_empty_supported_commands( } } -// Publishing Cluster Revision for ApplicationMonitoring Cluster -void uic_mqtt_dotdot_application_monitoring_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for WindowCovering Cluster +void uic_mqtt_dotdot_window_covering_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/ApplicationMonitoring/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/WindowCovering/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -110308,13 +107968,13 @@ void uic_mqtt_dotdot_application_monitoring_publish_cluster_revision(const char* true); } -// Unretain Cluster Revision for ApplicationMonitoring Cluster -void uic_mqtt_dotdot_application_monitoring_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for WindowCovering Cluster +void uic_mqtt_dotdot_window_covering_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/ApplicationMonitoring/Attributes/ClusterRevision"; + + "/WindowCovering/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -110324,28 +107984,12 @@ void uic_mqtt_dotdot_application_monitoring_unretain_cluster_revision(const char // clang-format off } -static inline bool uic_mqtt_dotdot_application_monitoring_log_entry_is_supported( +static inline bool uic_mqtt_dotdot_window_covering_up_or_open_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - const char* timestamp_value; - memset(×tamp_value, 0x00, sizeof(timestamp_value)); - LoggingLevelEnum log_level_value; - memset(&log_level_value, 0x00, sizeof(log_level_value)); - const char* log_tag_value; - memset(&log_tag_value, 0x00, sizeof(log_tag_value)); - const char* log_message_value; - memset(&log_message_value, 0x00, sizeof(log_message_value)); - for (const auto& callback: uic_mqtt_dotdot_application_monitoring_log_entry_callback) { + for (const auto& callback: uic_mqtt_dotdot_window_covering_up_or_open_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - timestamp_value, - - log_level_value, - - log_tag_value, - - log_message_value ) == SL_STATUS_OK) { return true; @@ -110354,175 +107998,121 @@ static inline bool uic_mqtt_dotdot_application_monitoring_log_entry_is_supported return false; } - -static inline bool uic_mqtt_dotdot_application_monitoring_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_window_covering_down_or_close_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_application_monitoring_write_attributes_callback) { - uic_mqtt_dotdot_application_monitoring_state_t application_monitoring_new_state = {}; - uic_mqtt_dotdot_application_monitoring_updated_state_t application_monitoring_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - application_monitoring_new_state, - application_monitoring_new_updated_state - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_window_covering_down_or_close_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_application_monitoring_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_window_covering_stop_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_application_monitoring_force_read_attributes_callback) { - uic_mqtt_dotdot_application_monitoring_updated_state_t application_monitoring_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - application_monitoring_force_update - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_window_covering_stop_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for ApplicationMonitoring Cluster -void uic_mqtt_dotdot_application_monitoring_publish_supported_commands( +static inline bool uic_mqtt_dotdot_window_covering_go_to_lift_value_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_application_monitoring_log_entry_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("LogEntry")"; - } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_application_monitoring_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + uint16_t lift_value_value; + memset(&lift_value_value, 0x00, sizeof(lift_value_value)); + for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_lift_value_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + lift_value_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_application_monitoring_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_window_covering_go_to_lift_percentage_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t percentage_lift_value_value; + memset(&percentage_lift_value_value, 0x00, sizeof(percentage_lift_value_value)); + for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_lift_percentage_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + percentage_lift_value_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - - topic += "/ApplicationMonitoring/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + return false; +} +static inline bool uic_mqtt_dotdot_window_covering_go_to_tilt_value_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t tilt_value_value; + memset(&tilt_value_value, 0x00, sizeof(tilt_value_value)); + for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_tilt_value_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + tilt_value_value - attributes_topic += "/ApplicationMonitoring/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + ) == SL_STATUS_OK) { + return true; } } -} -// Publishing empty/no Supported Commands for ApplicationMonitoring Cluster -void uic_mqtt_dotdot_application_monitoring_publish_empty_supported_commands( - const dotdot_unid_t unid - ) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ApplicationMonitoring/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + return false; } - -// Publishing Cluster Revision for NameAndLocation Cluster -void uic_mqtt_dotdot_name_and_location_publish_cluster_revision(const char* base_topic, uint16_t value) +static inline bool uic_mqtt_dotdot_window_covering_go_to_tilt_percentage_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string cluster_topic = std::string(base_topic) + "/NameAndLocation/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} + uint8_t percentage_tilt_value_value; + memset(&percentage_tilt_value_value, 0x00, sizeof(percentage_tilt_value_value)); + for (const auto& callback: uic_mqtt_dotdot_window_covering_go_to_tilt_percentage_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + percentage_tilt_value_value + + ) == SL_STATUS_OK) { + return true; + } + } -// Unretain Cluster Revision for NameAndLocation Cluster -void uic_mqtt_dotdot_name_and_location_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/NameAndLocation/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - -static inline bool uic_mqtt_dotdot_name_and_location_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_window_covering_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_name_and_location_write_attributes_callback) { - uic_mqtt_dotdot_name_and_location_state_t name_and_location_new_state = {}; - uic_mqtt_dotdot_name_and_location_updated_state_t name_and_location_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_window_covering_write_attributes_callback) { + uic_mqtt_dotdot_window_covering_state_t window_covering_new_state = {}; + uic_mqtt_dotdot_window_covering_updated_state_t window_covering_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - name_and_location_new_state, - name_and_location_new_updated_state + window_covering_new_state, + window_covering_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -110530,17 +108120,17 @@ static inline bool uic_mqtt_dotdot_name_and_location_write_attributes_is_support return false; } -static inline bool uic_mqtt_dotdot_name_and_location_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_window_covering_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_name_and_location_force_read_attributes_callback) { - uic_mqtt_dotdot_name_and_location_updated_state_t name_and_location_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_window_covering_force_read_attributes_callback) { + uic_mqtt_dotdot_window_covering_updated_state_t window_covering_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - name_and_location_force_update + window_covering_force_update ) == SL_STATUS_OK) { return true; } @@ -110548,8 +108138,8 @@ static inline bool uic_mqtt_dotdot_name_and_location_force_read_attributes_is_su return false; } -// Publishing Supported Commands for NameAndLocation Cluster -void uic_mqtt_dotdot_name_and_location_publish_supported_commands( +// Publishing Supported Commands for WindowCovering Cluster +void uic_mqtt_dotdot_window_covering_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -110558,9 +108148,58 @@ void uic_mqtt_dotdot_name_and_location_publish_supported_commands( ss.str(""); // check if there is callback for each command + if (uic_mqtt_dotdot_window_covering_up_or_open_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("UpOrOpen")"; + } + if (uic_mqtt_dotdot_window_covering_down_or_close_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DownOrClose")"; + } + if (uic_mqtt_dotdot_window_covering_stop_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Stop")"; + } + if (uic_mqtt_dotdot_window_covering_go_to_lift_value_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GoToLiftValue")"; + } + if (uic_mqtt_dotdot_window_covering_go_to_lift_percentage_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GoToLiftPercentage")"; + } + if (uic_mqtt_dotdot_window_covering_go_to_tilt_value_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GoToTiltValue")"; + } + if (uic_mqtt_dotdot_window_covering_go_to_tilt_percentage_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GoToTiltPercentage")"; + } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_name_and_location_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_window_covering_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -110569,7 +108208,7 @@ void uic_mqtt_dotdot_name_and_location_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_name_and_location_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_window_covering_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -110580,7 +108219,7 @@ void uic_mqtt_dotdot_name_and_location_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/NameAndLocation/SupportedCommands"; + topic += "/WindowCovering/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -110592,7 +108231,7 @@ void uic_mqtt_dotdot_name_and_location_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/NameAndLocation/Attributes"; + attributes_topic += "/WindowCovering/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -110603,14 +108242,14 @@ void uic_mqtt_dotdot_name_and_location_publish_supported_commands( } } -// Publishing empty/no Supported Commands for NameAndLocation Cluster -void uic_mqtt_dotdot_name_and_location_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for WindowCovering Cluster +void uic_mqtt_dotdot_window_covering_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/NameAndLocation/SupportedCommands"; + topic += "/WindowCovering/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -110620,10 +108259,10 @@ void uic_mqtt_dotdot_name_and_location_publish_empty_supported_commands( } } -// Publishing Cluster Revision for ConfigurationParameters Cluster -void uic_mqtt_dotdot_configuration_parameters_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for BarrierControl Cluster +void uic_mqtt_dotdot_barrier_control_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/ConfigurationParameters/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/BarrierControl/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -110640,13 +108279,13 @@ void uic_mqtt_dotdot_configuration_parameters_publish_cluster_revision(const cha true); } -// Unretain Cluster Revision for ConfigurationParameters Cluster -void uic_mqtt_dotdot_configuration_parameters_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for BarrierControl Cluster +void uic_mqtt_dotdot_barrier_control_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/ConfigurationParameters/Attributes/ClusterRevision"; + + "/BarrierControl/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -110656,16 +108295,16 @@ void uic_mqtt_dotdot_configuration_parameters_unretain_cluster_revision(const ch // clang-format off } -static inline bool uic_mqtt_dotdot_configuration_parameters_discover_parameter_is_supported( +static inline bool uic_mqtt_dotdot_barrier_control_go_to_percent_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - uint16_t parameter_id_value; - memset(¶meter_id_value, 0x00, sizeof(parameter_id_value)); - for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_discover_parameter_callback) { + uint8_t percent_open_value; + memset(&percent_open_value, 0x00, sizeof(percent_open_value)); + for (const auto& callback: uic_mqtt_dotdot_barrier_control_go_to_percent_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - parameter_id_value + percent_open_value ) == SL_STATUS_OK) { return true; @@ -110674,56 +108313,12 @@ static inline bool uic_mqtt_dotdot_configuration_parameters_discover_parameter_i return false; } -static inline bool uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_is_supported( +static inline bool uic_mqtt_dotdot_barrier_control_stop_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_configuration_parameters_set_parameter_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t parameter_id_value; - memset(¶meter_id_value, 0x00, sizeof(parameter_id_value)); - int64_t value_value; - memset(&value_value, 0x00, sizeof(value_value)); - for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_set_parameter_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - parameter_id_value, - - value_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - uint16_t first_parameter_id_value; - memset(&first_parameter_id_value, 0x00, sizeof(first_parameter_id_value)); - uint16_t last_parameter_id_value; - memset(&last_parameter_id_value, 0x00, sizeof(last_parameter_id_value)); - for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback) { + for (const auto& callback: uic_mqtt_dotdot_barrier_control_stop_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - first_parameter_id_value, - - last_parameter_id_value ) == SL_STATUS_OK) { return true; @@ -110733,20 +108328,20 @@ static inline bool uic_mqtt_dotdot_configuration_parameters_discover_parameter_r return false; } -static inline bool uic_mqtt_dotdot_configuration_parameters_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_barrier_control_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_write_attributes_callback) { - uic_mqtt_dotdot_configuration_parameters_state_t configuration_parameters_new_state = {}; - uic_mqtt_dotdot_configuration_parameters_updated_state_t configuration_parameters_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_barrier_control_write_attributes_callback) { + uic_mqtt_dotdot_barrier_control_state_t barrier_control_new_state = {}; + uic_mqtt_dotdot_barrier_control_updated_state_t barrier_control_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - configuration_parameters_new_state, - configuration_parameters_new_updated_state + barrier_control_new_state, + barrier_control_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -110754,17 +108349,17 @@ static inline bool uic_mqtt_dotdot_configuration_parameters_write_attributes_is_ return false; } -static inline bool uic_mqtt_dotdot_configuration_parameters_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_barrier_control_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_force_read_attributes_callback) { - uic_mqtt_dotdot_configuration_parameters_updated_state_t configuration_parameters_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_barrier_control_force_read_attributes_callback) { + uic_mqtt_dotdot_barrier_control_updated_state_t barrier_control_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - configuration_parameters_force_update + barrier_control_force_update ) == SL_STATUS_OK) { return true; } @@ -110772,8 +108367,8 @@ static inline bool uic_mqtt_dotdot_configuration_parameters_force_read_attribute return false; } -// Publishing Supported Commands for ConfigurationParameters Cluster -void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( +// Publishing Supported Commands for BarrierControl Cluster +void uic_mqtt_dotdot_barrier_control_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -110782,37 +108377,23 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_configuration_parameters_discover_parameter_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("DiscoverParameter")"; - } - if (uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("DefaultResetAllParameters")"; - } - if (uic_mqtt_dotdot_configuration_parameters_set_parameter_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_barrier_control_go_to_percent_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("SetParameter")"; + ss << R"("GoToPercent")"; } - if (uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_barrier_control_stop_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("DiscoverParameterRange")"; + ss << R"("Stop")"; } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_configuration_parameters_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_barrier_control_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -110821,7 +108402,7 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_configuration_parameters_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_barrier_control_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -110832,7 +108413,7 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ConfigurationParameters/SupportedCommands"; + topic += "/BarrierControl/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -110844,7 +108425,7 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/ConfigurationParameters/Attributes"; + attributes_topic += "/BarrierControl/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -110855,14 +108436,14 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( } } -// Publishing empty/no Supported Commands for ConfigurationParameters Cluster -void uic_mqtt_dotdot_configuration_parameters_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for BarrierControl Cluster +void uic_mqtt_dotdot_barrier_control_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/ConfigurationParameters/SupportedCommands"; + topic += "/BarrierControl/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -110872,10 +108453,10 @@ void uic_mqtt_dotdot_configuration_parameters_publish_empty_supported_commands( } } -// Publishing Cluster Revision for AoXLocator Cluster -void uic_mqtt_dotdot_aox_locator_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for PumpConfigurationAndControl Cluster +void uic_mqtt_dotdot_pump_configuration_and_control_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/AoXLocator/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/PumpConfigurationAndControl/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -110892,13 +108473,13 @@ void uic_mqtt_dotdot_aox_locator_publish_cluster_revision(const char* base_topic true); } -// Unretain Cluster Revision for AoXLocator Cluster -void uic_mqtt_dotdot_aox_locator_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for PumpConfigurationAndControl Cluster +void uic_mqtt_dotdot_pump_configuration_and_control_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/AoXLocator/Attributes/ClusterRevision"; + + "/PumpConfigurationAndControl/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -110908,113 +108489,21 @@ void uic_mqtt_dotdot_aox_locator_unretain_cluster_revision(const char* base_topi // clang-format off } -static inline bool uic_mqtt_dotdot_aox_locator_iq_report_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* tag_unid_value; - memset(&tag_unid_value, 0x00, sizeof(tag_unid_value)); - uint8_t channel_value; - memset(&channel_value, 0x00, sizeof(channel_value)); - int8_t rssi_value; - memset(&rssi_value, 0x00, sizeof(rssi_value)); - int32_t sequence_value; - memset(&sequence_value, 0x00, sizeof(sequence_value)); - for (const auto& callback: uic_mqtt_dotdot_aox_locator_iq_report_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - tag_unid_value, - - channel_value, - - rssi_value, - - 0, nullptr, - - sequence_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_aox_locator_angle_report_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* tag_unid_value; - memset(&tag_unid_value, 0x00, sizeof(tag_unid_value)); - SphericalCoordinates direction_value; - memset(&direction_value, 0x00, sizeof(direction_value)); - SphericalCoordinates deviation_value; - memset(&deviation_value, 0x00, sizeof(deviation_value)); - int32_t sequence_value; - memset(&sequence_value, 0x00, sizeof(sequence_value)); - for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_report_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - tag_unid_value, - - direction_value, - - deviation_value, - - sequence_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_aox_locator_angle_correction_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - const char* tag_unid_value; - memset(&tag_unid_value, 0x00, sizeof(tag_unid_value)); - SphericalCoordinates direction_value; - memset(&direction_value, 0x00, sizeof(direction_value)); - SphericalCoordinates deviation_value; - memset(&deviation_value, 0x00, sizeof(deviation_value)); - int32_t sequence_value; - memset(&sequence_value, 0x00, sizeof(sequence_value)); - for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_correction_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - tag_unid_value, - - direction_value, - - deviation_value, - - sequence_value - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_aox_locator_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_pump_configuration_and_control_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_aox_locator_write_attributes_callback) { - uic_mqtt_dotdot_aox_locator_state_t aox_locator_new_state = {}; - uic_mqtt_dotdot_aox_locator_updated_state_t aox_locator_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_pump_configuration_and_control_write_attributes_callback) { + uic_mqtt_dotdot_pump_configuration_and_control_state_t pump_configuration_and_control_new_state = {}; + uic_mqtt_dotdot_pump_configuration_and_control_updated_state_t pump_configuration_and_control_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - aox_locator_new_state, - aox_locator_new_updated_state + pump_configuration_and_control_new_state, + pump_configuration_and_control_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -111022,17 +108511,17 @@ static inline bool uic_mqtt_dotdot_aox_locator_write_attributes_is_supported( return false; } -static inline bool uic_mqtt_dotdot_aox_locator_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_pump_configuration_and_control_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_aox_locator_force_read_attributes_callback) { - uic_mqtt_dotdot_aox_locator_updated_state_t aox_locator_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_pump_configuration_and_control_force_read_attributes_callback) { + uic_mqtt_dotdot_pump_configuration_and_control_updated_state_t pump_configuration_and_control_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - aox_locator_force_update + pump_configuration_and_control_force_update ) == SL_STATUS_OK) { return true; } @@ -111040,8 +108529,8 @@ static inline bool uic_mqtt_dotdot_aox_locator_force_read_attributes_is_supporte return false; } -// Publishing Supported Commands for AoXLocator Cluster -void uic_mqtt_dotdot_aox_locator_publish_supported_commands( +// Publishing Supported Commands for PumpConfigurationAndControl Cluster +void uic_mqtt_dotdot_pump_configuration_and_control_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -111050,50 +108539,29 @@ void uic_mqtt_dotdot_aox_locator_publish_supported_commands( ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_aox_locator_iq_report_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("IQReport")"; - } - if (uic_mqtt_dotdot_aox_locator_angle_report_is_supported(unid, endpoint_id)) { + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_pump_configuration_and_control_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("AngleReport")"; + ss << R"("WriteAttributes")"; } - if (uic_mqtt_dotdot_aox_locator_angle_correction_is_supported(unid, endpoint_id)) { + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_pump_configuration_and_control_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("AngleCorrection")"; - } - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_aox_locator_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_aox_locator_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("ForceReadAttributes")"; } // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/AoXLocator/SupportedCommands"; + topic += "/PumpConfigurationAndControl/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -111105,7 +108573,7 @@ void uic_mqtt_dotdot_aox_locator_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/AoXLocator/Attributes"; + attributes_topic += "/PumpConfigurationAndControl/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111116,14 +108584,14 @@ void uic_mqtt_dotdot_aox_locator_publish_supported_commands( } } -// Publishing empty/no Supported Commands for AoXLocator Cluster -void uic_mqtt_dotdot_aox_locator_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for PumpConfigurationAndControl Cluster +void uic_mqtt_dotdot_pump_configuration_and_control_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/AoXLocator/SupportedCommands"; + topic += "/PumpConfigurationAndControl/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111133,10 +108601,10 @@ void uic_mqtt_dotdot_aox_locator_publish_empty_supported_commands( } } -// Publishing Cluster Revision for AoXPositionEstimation Cluster -void uic_mqtt_dotdot_aox_position_estimation_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for Thermostat Cluster +void uic_mqtt_dotdot_thermostat_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/AoXPositionEstimation/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/Thermostat/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -111153,13 +108621,13 @@ void uic_mqtt_dotdot_aox_position_estimation_publish_cluster_revision(const char true); } -// Unretain Cluster Revision for AoXPositionEstimation Cluster -void uic_mqtt_dotdot_aox_position_estimation_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for Thermostat Cluster +void uic_mqtt_dotdot_thermostat_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/AoXPositionEstimation/Attributes/ClusterRevision"; + + "/Thermostat/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -111169,21 +108637,187 @@ void uic_mqtt_dotdot_aox_position_estimation_unretain_cluster_revision(const cha // clang-format off } +static inline bool uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + SetpointRaiseOrLowerMode mode_value; + memset(&mode_value, 0x00, sizeof(mode_value)); + int8_t amount_value; + memset(&amount_value, 0x00, sizeof(amount_value)); + for (const auto& callback: uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + mode_value, + + amount_value + + ) == SL_STATUS_OK) { + return true; + } + } -static inline bool uic_mqtt_dotdot_aox_position_estimation_write_attributes_is_supported( + return false; +} +static inline bool uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback) { - uic_mqtt_dotdot_aox_position_estimation_state_t aox_position_estimation_new_state = {}; - uic_mqtt_dotdot_aox_position_estimation_updated_state_t aox_position_estimation_new_updated_state = {}; + uint8_t number_of_transitions_value; + memset(&number_of_transitions_value, 0x00, sizeof(number_of_transitions_value)); + uint8_t day_of_week_value; + memset(&day_of_week_value, 0x00, sizeof(day_of_week_value)); + uint8_t mode_value; + memset(&mode_value, 0x00, sizeof(mode_value)); + for (const auto& callback: uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + number_of_transitions_value, + + day_of_week_value, + + mode_value, + + 0, nullptr + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_thermostat_set_weekly_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t number_of_transitions_value; + memset(&number_of_transitions_value, 0x00, sizeof(number_of_transitions_value)); + uint8_t day_of_week_value; + memset(&day_of_week_value, 0x00, sizeof(day_of_week_value)); + uint8_t mode_value; + memset(&mode_value, 0x00, sizeof(mode_value)); + for (const auto& callback: uic_mqtt_dotdot_thermostat_set_weekly_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + number_of_transitions_value, + + day_of_week_value, + + mode_value, + + 0, nullptr + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_thermostat_get_relay_status_log_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t time_of_day_value; + memset(&time_of_day_value, 0x00, sizeof(time_of_day_value)); + uint8_t relay_status_value; + memset(&relay_status_value, 0x00, sizeof(relay_status_value)); + int16_t local_temperature_value; + memset(&local_temperature_value, 0x00, sizeof(local_temperature_value)); + uint8_t humidity_percentage_value; + memset(&humidity_percentage_value, 0x00, sizeof(humidity_percentage_value)); + int16_t set_point_value; + memset(&set_point_value, 0x00, sizeof(set_point_value)); + uint16_t unread_entries_value; + memset(&unread_entries_value, 0x00, sizeof(unread_entries_value)); + for (const auto& callback: uic_mqtt_dotdot_thermostat_get_relay_status_log_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + time_of_day_value, + + relay_status_value, + + local_temperature_value, + + humidity_percentage_value, + + set_point_value, + + unread_entries_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_thermostat_get_weekly_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t days_to_return_value; + memset(&days_to_return_value, 0x00, sizeof(days_to_return_value)); + uint8_t mode_to_return_value; + memset(&mode_to_return_value, 0x00, sizeof(mode_to_return_value)); + for (const auto& callback: uic_mqtt_dotdot_thermostat_get_weekly_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + days_to_return_value, + + mode_to_return_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_thermostat_clear_weekly_schedule_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_thermostat_clear_weekly_schedule_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_thermostat_get_relay_status_log_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_thermostat_get_relay_status_log_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_thermostat_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_thermostat_write_attributes_callback) { + uic_mqtt_dotdot_thermostat_state_t thermostat_new_state = {}; + uic_mqtt_dotdot_thermostat_updated_state_t thermostat_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - aox_position_estimation_new_state, - aox_position_estimation_new_updated_state + thermostat_new_state, + thermostat_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -111191,17 +108825,17 @@ static inline bool uic_mqtt_dotdot_aox_position_estimation_write_attributes_is_s return false; } -static inline bool uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_thermostat_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback) { - uic_mqtt_dotdot_aox_position_estimation_updated_state_t aox_position_estimation_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_thermostat_force_read_attributes_callback) { + uic_mqtt_dotdot_thermostat_updated_state_t thermostat_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - aox_position_estimation_force_update + thermostat_force_update ) == SL_STATUS_OK) { return true; } @@ -111209,8 +108843,8 @@ static inline bool uic_mqtt_dotdot_aox_position_estimation_force_read_attributes return false; } -// Publishing Supported Commands for AoXPositionEstimation Cluster -void uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands( +// Publishing Supported Commands for Thermostat Cluster +void uic_mqtt_dotdot_thermostat_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -111219,42 +108853,91 @@ void uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands( ss.str(""); // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_aox_position_estimation_write_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_thermostat_setpoint_raise_or_lower_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("WriteAttributes")"; + ss << R"("SetpointRaiseOrLower")"; } - - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_thermostat_get_weekly_schedule_response_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } first_command = false; - ss << R"("ForceReadAttributes")"; + ss << R"("GetWeeklyScheduleResponse")"; } - - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/AoXPositionEstimation/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/AoXPositionEstimation/Attributes"; - + if (uic_mqtt_dotdot_thermostat_set_weekly_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetWeeklySchedule")"; + } + if (uic_mqtt_dotdot_thermostat_get_relay_status_log_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetRelayStatusLogResponse")"; + } + if (uic_mqtt_dotdot_thermostat_get_weekly_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetWeeklySchedule")"; + } + if (uic_mqtt_dotdot_thermostat_clear_weekly_schedule_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ClearWeeklySchedule")"; + } + if (uic_mqtt_dotdot_thermostat_get_relay_status_log_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetRelayStatusLog")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_thermostat_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_thermostat_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Thermostat/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/Thermostat/Attributes"; + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), EMPTY_VALUE_ARRAY, @@ -111264,14 +108947,14 @@ void uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands( } } -// Publishing empty/no Supported Commands for AoXPositionEstimation Cluster -void uic_mqtt_dotdot_aox_position_estimation_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for Thermostat Cluster +void uic_mqtt_dotdot_thermostat_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/AoXPositionEstimation/SupportedCommands"; + topic += "/Thermostat/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111281,10 +108964,10 @@ void uic_mqtt_dotdot_aox_position_estimation_publish_empty_supported_commands( } } -// Publishing Cluster Revision for ProtocolController-NetworkManagement Cluster -void uic_mqtt_dotdot_protocol_controller_network_management_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for FanControl Cluster +void uic_mqtt_dotdot_fan_control_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/ProtocolController/NetworkManagement/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/FanControl/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -111301,13 +108984,13 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_cluster_revi true); } -// Unretain Cluster Revision for ProtocolController-NetworkManagement Cluster -void uic_mqtt_dotdot_protocol_controller_network_management_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for FanControl Cluster +void uic_mqtt_dotdot_fan_control_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/ProtocolController/NetworkManagement/Attributes/ClusterRevision"; + + "/FanControl/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -111317,35 +109000,21 @@ void uic_mqtt_dotdot_protocol_controller_network_management_unretain_cluster_rev // clang-format off } -static inline bool uic_mqtt_dotdot_protocol_controller_network_management_write_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { - return true; - } - } - - return false; -} -static inline bool uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_fan_control_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback) { - uic_mqtt_dotdot_protocol_controller_network_management_state_t protocol_controller_network_management_new_state = {}; - uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t protocol_controller_network_management_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_fan_control_write_attributes_callback) { + uic_mqtt_dotdot_fan_control_state_t fan_control_new_state = {}; + uic_mqtt_dotdot_fan_control_updated_state_t fan_control_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - protocol_controller_network_management_new_state, - protocol_controller_network_management_new_updated_state + fan_control_new_state, + fan_control_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -111353,17 +109022,17 @@ static inline bool uic_mqtt_dotdot_protocol_controller_network_management_write_ return false; } -static inline bool uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_fan_control_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback) { - uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t protocol_controller_network_management_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_fan_control_force_read_attributes_callback) { + uic_mqtt_dotdot_fan_control_updated_state_t fan_control_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - protocol_controller_network_management_force_update + fan_control_force_update ) == SL_STATUS_OK) { return true; } @@ -111371,8 +109040,8 @@ static inline bool uic_mqtt_dotdot_protocol_controller_network_management_force_ return false; } -// Publishing Supported Commands for ProtocolController-NetworkManagement Cluster -void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_commands( +// Publishing Supported Commands for FanControl Cluster +void uic_mqtt_dotdot_fan_control_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -111381,16 +109050,9 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_co ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_protocol_controller_network_management_write_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("Write")"; - } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_fan_control_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -111399,7 +109061,7 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_co } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_fan_control_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -111409,8 +109071,8 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_co // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); - - topic += "/ProtocolController/NetworkManagement/SupportedCommands"; + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/FanControl/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -111421,8 +109083,8 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_co // There are no supported commands, but make sure we publish some // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - - attributes_topic += "/ProtocolController/NetworkManagement/Attributes"; + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/FanControl/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111433,13 +109095,14 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_co } } -// Publishing empty/no Supported Commands for ProtocolController-NetworkManagement Cluster -void uic_mqtt_dotdot_protocol_controller_network_management_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for FanControl Cluster +void uic_mqtt_dotdot_fan_control_publish_empty_supported_commands( const dotdot_unid_t unid - ) + , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ProtocolController/NetworkManagement/SupportedCommands"; + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/FanControl/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111449,10 +109112,10 @@ void uic_mqtt_dotdot_protocol_controller_network_management_publish_empty_suppor } } -// Publishing Cluster Revision for Descriptor Cluster -void uic_mqtt_dotdot_descriptor_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for DehumidificationControl Cluster +void uic_mqtt_dotdot_dehumidification_control_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/Descriptor/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/DehumidificationControl/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -111469,13 +109132,13 @@ void uic_mqtt_dotdot_descriptor_publish_cluster_revision(const char* base_topic, true); } -// Unretain Cluster Revision for Descriptor Cluster -void uic_mqtt_dotdot_descriptor_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for DehumidificationControl Cluster +void uic_mqtt_dotdot_dehumidification_control_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/Descriptor/Attributes/ClusterRevision"; + + "/DehumidificationControl/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -111486,20 +109149,20 @@ void uic_mqtt_dotdot_descriptor_unretain_cluster_revision(const char* base_topic } -static inline bool uic_mqtt_dotdot_descriptor_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_dehumidification_control_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_descriptor_write_attributes_callback) { - uic_mqtt_dotdot_descriptor_state_t descriptor_new_state = {}; - uic_mqtt_dotdot_descriptor_updated_state_t descriptor_new_updated_state = {}; + for (const auto& callback: uic_mqtt_dotdot_dehumidification_control_write_attributes_callback) { + uic_mqtt_dotdot_dehumidification_control_state_t dehumidification_control_new_state = {}; + uic_mqtt_dotdot_dehumidification_control_updated_state_t dehumidification_control_new_updated_state = {}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - descriptor_new_state, - descriptor_new_updated_state + dehumidification_control_new_state, + dehumidification_control_new_updated_state ) == SL_STATUS_OK) { return true; } @@ -111507,17 +109170,17 @@ static inline bool uic_mqtt_dotdot_descriptor_write_attributes_is_supported( return false; } -static inline bool uic_mqtt_dotdot_descriptor_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_dehumidification_control_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_descriptor_force_read_attributes_callback) { - uic_mqtt_dotdot_descriptor_updated_state_t descriptor_force_update = {0}; + for (const auto& callback: uic_mqtt_dotdot_dehumidification_control_force_read_attributes_callback) { + uic_mqtt_dotdot_dehumidification_control_updated_state_t dehumidification_control_force_update = {0}; if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - descriptor_force_update + dehumidification_control_force_update ) == SL_STATUS_OK) { return true; } @@ -111525,8 +109188,8 @@ static inline bool uic_mqtt_dotdot_descriptor_force_read_attributes_is_supported return false; } -// Publishing Supported Commands for Descriptor Cluster -void uic_mqtt_dotdot_descriptor_publish_supported_commands( +// Publishing Supported Commands for DehumidificationControl Cluster +void uic_mqtt_dotdot_dehumidification_control_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -111537,7 +109200,7 @@ void uic_mqtt_dotdot_descriptor_publish_supported_commands( // check if there is callback for each command // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_descriptor_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_dehumidification_control_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -111546,7 +109209,7 @@ void uic_mqtt_dotdot_descriptor_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_descriptor_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_dehumidification_control_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -111557,7 +109220,7 @@ void uic_mqtt_dotdot_descriptor_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Descriptor/SupportedCommands"; + topic += "/DehumidificationControl/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -111569,7 +109232,7 @@ void uic_mqtt_dotdot_descriptor_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/Descriptor/Attributes"; + attributes_topic += "/DehumidificationControl/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111580,14 +109243,14 @@ void uic_mqtt_dotdot_descriptor_publish_supported_commands( } } -// Publishing empty/no Supported Commands for Descriptor Cluster -void uic_mqtt_dotdot_descriptor_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for DehumidificationControl Cluster +void uic_mqtt_dotdot_dehumidification_control_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/Descriptor/SupportedCommands"; + topic += "/DehumidificationControl/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111597,10 +109260,10 @@ void uic_mqtt_dotdot_descriptor_publish_empty_supported_commands( } } -// Publishing Cluster Revision for UnifyFanControl Cluster -void uic_mqtt_dotdot_unify_fan_control_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for ThermostatUserInterfaceConfiguration Cluster +void uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/ThermostatUserInterfaceConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -111617,13 +109280,13 @@ void uic_mqtt_dotdot_unify_fan_control_publish_cluster_revision(const char* base true); } -// Unretain Cluster Revision for UnifyFanControl Cluster -void uic_mqtt_dotdot_unify_fan_control_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for ThermostatUserInterfaceConfiguration Cluster +void uic_mqtt_dotdot_thermostat_user_interface_configuration_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/UnifyFanControl/Attributes/ClusterRevision"; + + "/ThermostatUserInterfaceConfiguration/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -111633,80 +109296,48 @@ void uic_mqtt_dotdot_unify_fan_control_unretain_cluster_revision(const char* bas // clang-format off } -static inline bool uic_mqtt_dotdot_unify_fan_control_set_fan_mode_is_supported( + +static inline bool uic_mqtt_dotdot_thermostat_user_interface_configuration_write_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - ZWaveFanModeEnum fan_mode_value; - memset(&fan_mode_value, 0x00, sizeof(fan_mode_value)); - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - , - fan_mode_value - - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_thermostat_user_interface_configuration_write_attributes_callback) { + uic_mqtt_dotdot_thermostat_user_interface_configuration_state_t thermostat_user_interface_configuration_new_state = {}; + uic_mqtt_dotdot_thermostat_user_interface_configuration_updated_state_t thermostat_user_interface_configuration_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + thermostat_user_interface_configuration_new_state, + thermostat_user_interface_configuration_new_updated_state + ) == SL_STATUS_OK) { return true; } } - return false; } -static inline bool uic_mqtt_dotdot_unify_fan_control_turn_off_is_supported( + +static inline bool uic_mqtt_dotdot_thermostat_user_interface_configuration_force_read_attributes_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_turn_off_callback) { - if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK - - ) == SL_STATUS_OK) { + for (const auto& callback: uic_mqtt_dotdot_thermostat_user_interface_configuration_force_read_attributes_callback) { + uic_mqtt_dotdot_thermostat_user_interface_configuration_updated_state_t thermostat_user_interface_configuration_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + thermostat_user_interface_configuration_force_update + ) == SL_STATUS_OK) { return true; } } - return false; } -static inline bool uic_mqtt_dotdot_unify_fan_control_write_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_write_attributes_callback) { - uic_mqtt_dotdot_unify_fan_control_state_t unify_fan_control_new_state = {}; - uic_mqtt_dotdot_unify_fan_control_updated_state_t unify_fan_control_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - unify_fan_control_new_state, - unify_fan_control_new_updated_state - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} - -static inline bool uic_mqtt_dotdot_unify_fan_control_force_read_attributes_is_supported( - const dotdot_unid_t unid, - dotdot_endpoint_id_t endpoint_id) -{ - for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback) { - uic_mqtt_dotdot_unify_fan_control_updated_state_t unify_fan_control_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - unify_fan_control_force_update - ) == SL_STATUS_OK) { - return true; - } - } - return false; -} - -// Publishing Supported Commands for UnifyFanControl Cluster -void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( +// Publishing Supported Commands for ThermostatUserInterfaceConfiguration Cluster +void uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_supported_commands( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { @@ -111715,23 +109346,9 @@ void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( ss.str(""); // check if there is callback for each command - if (uic_mqtt_dotdot_unify_fan_control_set_fan_mode_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("SetFanMode")"; - } - if (uic_mqtt_dotdot_unify_fan_control_turn_off_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("TurnOff")"; - } // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_unify_fan_control_write_attributes_is_supported(unid, endpoint_id)) { + if(uic_mqtt_dotdot_thermostat_user_interface_configuration_write_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -111740,7 +109357,7 @@ void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( } // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_unify_fan_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (uic_mqtt_dotdot_thermostat_user_interface_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { if (first_command == false) { ss << ", "; } @@ -111751,7 +109368,7 @@ void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( // Publish supported commands std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/UnifyFanControl/SupportedCommands"; + topic += "/ThermostatUserInterfaceConfiguration/SupportedCommands"; std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); if (first_command == false) { uic_mqtt_publish(topic.c_str(), @@ -111763,7 +109380,7 @@ void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( // SupportedCommands = [] if any attribute has been published for a cluster. std::string attributes_topic = "ucl/by-unid/" + std::string(unid); attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/UnifyFanControl/Attributes"; + attributes_topic += "/ThermostatUserInterfaceConfiguration/Attributes"; if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111774,14 +109391,14 @@ void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( } } -// Publishing empty/no Supported Commands for UnifyFanControl Cluster -void uic_mqtt_dotdot_unify_fan_control_publish_empty_supported_commands( +// Publishing empty/no Supported Commands for ThermostatUserInterfaceConfiguration Cluster +void uic_mqtt_dotdot_thermostat_user_interface_configuration_publish_empty_supported_commands( const dotdot_unid_t unid , dotdot_endpoint_id_t endpoint_id) { std::string topic = "ucl/by-unid/" + std::string(unid); topic += "/ep"+ std::to_string(endpoint_id); - topic += "/UnifyFanControl/SupportedCommands"; + topic += "/ThermostatUserInterfaceConfiguration/SupportedCommands"; if (uic_mqtt_count_topics(topic.c_str()) > 0) { uic_mqtt_publish(topic.c_str(), @@ -111791,10 +109408,10 @@ void uic_mqtt_dotdot_unify_fan_control_publish_empty_supported_commands( } } -// Publishing Cluster Revision for UnifyThermostat Cluster -void uic_mqtt_dotdot_unify_thermostat_publish_cluster_revision(const char* base_topic, uint16_t value) +// Publishing Cluster Revision for ColorControl Cluster +void uic_mqtt_dotdot_color_control_publish_cluster_revision(const char* base_topic, uint16_t value) { - std::string cluster_topic = std::string(base_topic) + "/UnifyThermostat/Attributes/ClusterRevision"; + std::string cluster_topic = std::string(base_topic) + "/ColorControl/Attributes/ClusterRevision"; // Publish Desired std::string pub_topic_des = cluster_topic + "/Desired"; std::string payload = std::string(R"({"value": )") @@ -111811,13 +109428,13 @@ void uic_mqtt_dotdot_unify_thermostat_publish_cluster_revision(const char* base_ true); } -// Unretain Cluster Revision for UnifyThermostat Cluster -void uic_mqtt_dotdot_unify_thermostat_unretain_cluster_revision(const char* base_topic) +// Unretain Cluster Revision for ColorControl Cluster +void uic_mqtt_dotdot_color_control_unretain_cluster_revision(const char* base_topic) { // clang-format on std::string cluster_topic = std::string(base_topic) - + "/UnifyThermostat/Attributes/ClusterRevision"; + + "/ColorControl/Attributes/ClusterRevision"; // Publish Desired std::string desired_topic = cluster_topic + "/Desired"; uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); @@ -111827,164 +109444,190 @@ void uic_mqtt_dotdot_unify_thermostat_unretain_cluster_revision(const char* base // clang-format off } - -static inline bool uic_mqtt_dotdot_unify_thermostat_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_color_control_move_to_hue_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_write_attributes_callback) { - uic_mqtt_dotdot_unify_thermostat_state_t unify_thermostat_new_state = {}; - uic_mqtt_dotdot_unify_thermostat_updated_state_t unify_thermostat_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - unify_thermostat_new_state, - unify_thermostat_new_updated_state - ) == SL_STATUS_OK) { + uint8_t hue_value; + memset(&hue_value, 0x00, sizeof(hue_value)); + CCDirection direction_value; + memset(&direction_value, 0x00, sizeof(direction_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_hue_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + hue_value, + + direction_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_unify_thermostat_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_color_control_move_hue_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback) { - uic_mqtt_dotdot_unify_thermostat_updated_state_t unify_thermostat_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - unify_thermostat_force_update - ) == SL_STATUS_OK) { + CCMoveMode move_mode_value; + memset(&move_mode_value, 0x00, sizeof(move_mode_value)); + uint8_t rate_value; + memset(&rate_value, 0x00, sizeof(rate_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_hue_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + move_mode_value, + + rate_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for UnifyThermostat Cluster -void uic_mqtt_dotdot_unify_thermostat_publish_supported_commands( +static inline bool uic_mqtt_dotdot_color_control_step_hue_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_unify_thermostat_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + CCStepMode step_mode_value; + memset(&step_mode_value, 0x00, sizeof(step_mode_value)); + uint8_t step_size_value; + memset(&step_size_value, 0x00, sizeof(step_size_value)); + uint8_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_step_hue_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + step_mode_value, + + step_size_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("WriteAttributes")"; } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_unify_thermostat_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_color_control_move_to_saturation_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t saturation_value; + memset(&saturation_value, 0x00, sizeof(saturation_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_saturation_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + saturation_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/UnifyThermostat/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/UnifyThermostat/Attributes"; - - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } - } + return false; } - -// Publishing empty/no Supported Commands for UnifyThermostat Cluster -void uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) +static inline bool uic_mqtt_dotdot_color_control_move_saturation_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) { - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/UnifyThermostat/SupportedCommands"; - - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + CCMoveMode move_mode_value; + memset(&move_mode_value, 0x00, sizeof(move_mode_value)); + uint8_t rate_value; + memset(&rate_value, 0x00, sizeof(rate_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_saturation_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + move_mode_value, + + rate_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } } -} - -// Publishing Cluster Revision for UnifyHumidityControl Cluster -void uic_mqtt_dotdot_unify_humidity_control_publish_cluster_revision(const char* base_topic, uint16_t value) -{ - std::string cluster_topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/ClusterRevision"; - // Publish Desired - std::string pub_topic_des = cluster_topic + "/Desired"; - std::string payload = std::string(R"({"value": )") - + std::to_string(value) + std::string("}"); - uic_mqtt_publish(pub_topic_des.c_str(), - payload.c_str(), - payload.size(), - true); - // Publish Reported - std::string pub_topic_rep = cluster_topic + "/Reported"; - uic_mqtt_publish(pub_topic_rep.c_str(), - payload.c_str(), - payload.size(), - true); -} -// Unretain Cluster Revision for UnifyHumidityControl Cluster -void uic_mqtt_dotdot_unify_humidity_control_unretain_cluster_revision(const char* base_topic) -{ - // clang-format on - std::string cluster_topic - = std::string(base_topic) - + "/UnifyHumidityControl/Attributes/ClusterRevision"; - // Publish Desired - std::string desired_topic = cluster_topic + "/Desired"; - uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); - // Publish Reported - std::string reported_topic = cluster_topic + "/Reported"; - uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); - // clang-format off + return false; } - -static inline bool uic_mqtt_dotdot_unify_humidity_control_mode_set_is_supported( +static inline bool uic_mqtt_dotdot_color_control_step_saturation_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - ModeType mode_value; - memset(&mode_value, 0x00, sizeof(mode_value)); - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_mode_set_callback) { + CCStepMode step_mode_value; + memset(&step_mode_value, 0x00, sizeof(step_mode_value)); + uint8_t step_size_value; + memset(&step_size_value, 0x00, sizeof(step_size_value)); + uint8_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_step_saturation_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - mode_value + step_mode_value, + + step_size_value, + + transition_time_value, + + options_mask_value, + + options_override_value ) == SL_STATUS_OK) { return true; @@ -111993,28 +109636,32 @@ static inline bool uic_mqtt_dotdot_unify_humidity_control_mode_set_is_supported( return false; } -static inline bool uic_mqtt_dotdot_unify_humidity_control_setpoint_set_is_supported( +static inline bool uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - SetpointType type_value; - memset(&type_value, 0x00, sizeof(type_value)); - uint8_t precision_value; - memset(&precision_value, 0x00, sizeof(precision_value)); - uint8_t scale_value; - memset(&scale_value, 0x00, sizeof(scale_value)); - int32_t value_value; - memset(&value_value, 0x00, sizeof(value_value)); - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback) { + uint8_t hue_value; + memset(&hue_value, 0x00, sizeof(hue_value)); + uint8_t saturation_value; + memset(&saturation_value, 0x00, sizeof(saturation_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_callback) { if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK , - type_value, + hue_value, - precision_value, + saturation_value, - scale_value, + transition_time_value, - value_value + options_mask_value, + + options_override_value ) == SL_STATUS_OK) { return true; @@ -112023,161 +109670,8211 @@ static inline bool uic_mqtt_dotdot_unify_humidity_control_setpoint_set_is_suppor return false; } - -static inline bool uic_mqtt_dotdot_unify_humidity_control_write_attributes_is_supported( +static inline bool uic_mqtt_dotdot_color_control_move_to_color_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback) { - uic_mqtt_dotdot_unify_humidity_control_state_t unify_humidity_control_new_state = {}; - uic_mqtt_dotdot_unify_humidity_control_updated_state_t unify_humidity_control_new_updated_state = {}; - - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - unify_humidity_control_new_state, - unify_humidity_control_new_updated_state - ) == SL_STATUS_OK) { + uint16_t colorx_value; + memset(&colorx_value, 0x00, sizeof(colorx_value)); + uint16_t colory_value; + memset(&colory_value, 0x00, sizeof(colory_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_color_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + colorx_value, + + colory_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -static inline bool uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_is_supported( +static inline bool uic_mqtt_dotdot_color_control_move_color_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback) { - uic_mqtt_dotdot_unify_humidity_control_updated_state_t unify_humidity_control_force_update = {0}; - if (callback( - unid, - endpoint_id, - UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, - unify_humidity_control_force_update - ) == SL_STATUS_OK) { + int16_t ratex_value; + memset(&ratex_value, 0x00, sizeof(ratex_value)); + int16_t ratey_value; + memset(&ratey_value, 0x00, sizeof(ratey_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_color_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + ratex_value, + + ratey_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { return true; } } + return false; } - -// Publishing Supported Commands for UnifyHumidityControl Cluster -void uic_mqtt_dotdot_unify_humidity_control_publish_supported_commands( +static inline bool uic_mqtt_dotdot_color_control_step_color_is_supported( const dotdot_unid_t unid, dotdot_endpoint_id_t endpoint_id) { - std::stringstream ss; - bool first_command = true; - ss.str(""); - - // check if there is callback for each command - if (uic_mqtt_dotdot_unify_humidity_control_mode_set_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("ModeSet")"; - } - if (uic_mqtt_dotdot_unify_humidity_control_setpoint_set_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + int16_t stepx_value; + memset(&stepx_value, 0x00, sizeof(stepx_value)); + int16_t stepy_value; + memset(&stepy_value, 0x00, sizeof(stepy_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_step_color_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + stepx_value, + + stepy_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("SetpointSet")"; } - // Check for a WriteAttributes Callback - if(uic_mqtt_dotdot_unify_humidity_control_write_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; - } - first_command = false; - ss << R"("WriteAttributes")"; - } + return false; +} +static inline bool uic_mqtt_dotdot_color_control_move_to_color_temperature_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t color_temperature_mireds_value; + memset(&color_temperature_mireds_value, 0x00, sizeof(color_temperature_mireds_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_to_color_temperature_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + color_temperature_mireds_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } - // Check for a ForceReadAttributes Callback - if (uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_is_supported(unid, endpoint_id)) { - if (first_command == false) { - ss << ", "; + return false; +} +static inline bool uic_mqtt_dotdot_color_control_enhanced_move_to_hue_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t enhanced_hue_value; + memset(&enhanced_hue_value, 0x00, sizeof(enhanced_hue_value)); + CCDirection direction_value; + memset(&direction_value, 0x00, sizeof(direction_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_move_to_hue_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + enhanced_hue_value, + + direction_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; } - first_command = false; - ss << R"("ForceReadAttributes")"; } - // Publish supported commands - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/UnifyHumidityControl/SupportedCommands"; - std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); - if (first_command == false) { - uic_mqtt_publish(topic.c_str(), - payload_str.c_str(), - payload_str.length(), - true); - } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { - // There are no supported commands, but make sure we publish some - // SupportedCommands = [] if any attribute has been published for a cluster. - std::string attributes_topic = "ucl/by-unid/" + std::string(unid); - attributes_topic += "/ep"+ std::to_string(endpoint_id); - attributes_topic += "/UnifyHumidityControl/Attributes"; + return false; +} +static inline bool uic_mqtt_dotdot_color_control_enhanced_move_hue_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CCMoveMode move_mode_value; + memset(&move_mode_value, 0x00, sizeof(move_mode_value)); + uint16_t rate_value; + memset(&rate_value, 0x00, sizeof(rate_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_move_hue_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + move_mode_value, + + rate_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } - if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); + return false; +} +static inline bool uic_mqtt_dotdot_color_control_enhanced_step_hue_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CCStepMode step_mode_value; + memset(&step_mode_value, 0x00, sizeof(step_mode_value)); + uint16_t step_size_value; + memset(&step_size_value, 0x00, sizeof(step_size_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_step_hue_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + step_mode_value, + + step_size_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_color_control_enhanced_move_to_hue_and_saturation_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t enhanced_hue_value; + memset(&enhanced_hue_value, 0x00, sizeof(enhanced_hue_value)); + uint8_t saturation_value; + memset(&saturation_value, 0x00, sizeof(saturation_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_enhanced_move_to_hue_and_saturation_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + enhanced_hue_value, + + saturation_value, + + transition_time_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_color_control_color_loop_set_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t update_flags_value; + memset(&update_flags_value, 0x00, sizeof(update_flags_value)); + ColorLoopSetAction action_value; + memset(&action_value, 0x00, sizeof(action_value)); + CCColorLoopDirection direction_value; + memset(&direction_value, 0x00, sizeof(direction_value)); + uint16_t time_value; + memset(&time_value, 0x00, sizeof(time_value)); + uint16_t start_hue_value; + memset(&start_hue_value, 0x00, sizeof(start_hue_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_color_loop_set_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + update_flags_value, + + action_value, + + direction_value, + + time_value, + + start_hue_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_color_control_stop_move_step_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_stop_move_step_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; } } + + return false; } +static inline bool uic_mqtt_dotdot_color_control_move_color_temperature_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CCMoveMode move_mode_value; + memset(&move_mode_value, 0x00, sizeof(move_mode_value)); + uint16_t rate_value; + memset(&rate_value, 0x00, sizeof(rate_value)); + CCMinMiredsField color_temperature_minimum_mireds_value; + memset(&color_temperature_minimum_mireds_value, 0x00, sizeof(color_temperature_minimum_mireds_value)); + CCMaxMiredsField color_temperature_maximum_mireds_value; + memset(&color_temperature_maximum_mireds_value, 0x00, sizeof(color_temperature_maximum_mireds_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_move_color_temperature_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + move_mode_value, + + rate_value, + + color_temperature_minimum_mireds_value, + + color_temperature_maximum_mireds_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_color_control_step_color_temperature_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CCStepMode step_mode_value; + memset(&step_mode_value, 0x00, sizeof(step_mode_value)); + uint16_t step_size_value; + memset(&step_size_value, 0x00, sizeof(step_size_value)); + uint16_t transition_time_value; + memset(&transition_time_value, 0x00, sizeof(transition_time_value)); + CCMinMiredsField color_temperature_minimum_mireds_value; + memset(&color_temperature_minimum_mireds_value, 0x00, sizeof(color_temperature_minimum_mireds_value)); + CCMaxMiredsField color_temperature_maximum_mireds_value; + memset(&color_temperature_maximum_mireds_value, 0x00, sizeof(color_temperature_maximum_mireds_value)); + uint8_t options_mask_value; + memset(&options_mask_value, 0x00, sizeof(options_mask_value)); + uint8_t options_override_value; + memset(&options_override_value, 0x00, sizeof(options_override_value)); + for (const auto& callback: uic_mqtt_dotdot_color_control_step_color_temperature_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + step_mode_value, + + step_size_value, + + transition_time_value, + + color_temperature_minimum_mireds_value, + + color_temperature_maximum_mireds_value, + + options_mask_value, + + options_override_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_color_control_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_color_control_write_attributes_callback) { + uic_mqtt_dotdot_color_control_state_t color_control_new_state = {}; + uic_mqtt_dotdot_color_control_updated_state_t color_control_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + color_control_new_state, + color_control_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_color_control_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_color_control_force_read_attributes_callback) { + uic_mqtt_dotdot_color_control_updated_state_t color_control_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + color_control_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ColorControl Cluster +void uic_mqtt_dotdot_color_control_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_color_control_move_to_hue_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToHue")"; + } + if (uic_mqtt_dotdot_color_control_move_hue_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveHue")"; + } + if (uic_mqtt_dotdot_color_control_step_hue_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StepHue")"; + } + if (uic_mqtt_dotdot_color_control_move_to_saturation_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToSaturation")"; + } + if (uic_mqtt_dotdot_color_control_move_saturation_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveSaturation")"; + } + if (uic_mqtt_dotdot_color_control_step_saturation_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StepSaturation")"; + } + if (uic_mqtt_dotdot_color_control_move_to_hue_and_saturation_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToHueAndSaturation")"; + } + if (uic_mqtt_dotdot_color_control_move_to_color_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToColor")"; + } + if (uic_mqtt_dotdot_color_control_move_color_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveColor")"; + } + if (uic_mqtt_dotdot_color_control_step_color_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StepColor")"; + } + if (uic_mqtt_dotdot_color_control_move_to_color_temperature_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveToColorTemperature")"; + } + if (uic_mqtt_dotdot_color_control_enhanced_move_to_hue_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("EnhancedMoveToHue")"; + } + if (uic_mqtt_dotdot_color_control_enhanced_move_hue_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("EnhancedMoveHue")"; + } + if (uic_mqtt_dotdot_color_control_enhanced_step_hue_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("EnhancedStepHue")"; + } + if (uic_mqtt_dotdot_color_control_enhanced_move_to_hue_and_saturation_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("EnhancedMoveToHueAndSaturation")"; + } + if (uic_mqtt_dotdot_color_control_color_loop_set_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ColorLoopSet")"; + } + if (uic_mqtt_dotdot_color_control_stop_move_step_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StopMoveStep")"; + } + if (uic_mqtt_dotdot_color_control_move_color_temperature_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("MoveColorTemperature")"; + } + if (uic_mqtt_dotdot_color_control_step_color_temperature_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StepColorTemperature")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_color_control_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_color_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ColorControl/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/ColorControl/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ColorControl Cluster +void uic_mqtt_dotdot_color_control_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ColorControl/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for BallastConfiguration Cluster +void uic_mqtt_dotdot_ballast_configuration_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/BallastConfiguration/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for BallastConfiguration Cluster +void uic_mqtt_dotdot_ballast_configuration_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/BallastConfiguration/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_ballast_configuration_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ballast_configuration_write_attributes_callback) { + uic_mqtt_dotdot_ballast_configuration_state_t ballast_configuration_new_state = {}; + uic_mqtt_dotdot_ballast_configuration_updated_state_t ballast_configuration_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ballast_configuration_new_state, + ballast_configuration_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_ballast_configuration_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ballast_configuration_force_read_attributes_callback) { + uic_mqtt_dotdot_ballast_configuration_updated_state_t ballast_configuration_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ballast_configuration_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for BallastConfiguration Cluster +void uic_mqtt_dotdot_ballast_configuration_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_ballast_configuration_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_ballast_configuration_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/BallastConfiguration/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/BallastConfiguration/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for BallastConfiguration Cluster +void uic_mqtt_dotdot_ballast_configuration_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/BallastConfiguration/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for IlluminanceMeasurement Cluster +void uic_mqtt_dotdot_illuminance_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/IlluminanceMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for IlluminanceMeasurement Cluster +void uic_mqtt_dotdot_illuminance_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/IlluminanceMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_illuminance_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_illuminance_measurement_write_attributes_callback) { + uic_mqtt_dotdot_illuminance_measurement_state_t illuminance_measurement_new_state = {}; + uic_mqtt_dotdot_illuminance_measurement_updated_state_t illuminance_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + illuminance_measurement_new_state, + illuminance_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_illuminance_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_illuminance_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_illuminance_measurement_updated_state_t illuminance_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + illuminance_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for IlluminanceMeasurement Cluster +void uic_mqtt_dotdot_illuminance_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_illuminance_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_illuminance_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IlluminanceMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/IlluminanceMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for IlluminanceMeasurement Cluster +void uic_mqtt_dotdot_illuminance_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IlluminanceMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for IlluminanceLevelSensing Cluster +void uic_mqtt_dotdot_illuminance_level_sensing_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/IlluminanceLevelSensing/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for IlluminanceLevelSensing Cluster +void uic_mqtt_dotdot_illuminance_level_sensing_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/IlluminanceLevelSensing/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_illuminance_level_sensing_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_illuminance_level_sensing_write_attributes_callback) { + uic_mqtt_dotdot_illuminance_level_sensing_state_t illuminance_level_sensing_new_state = {}; + uic_mqtt_dotdot_illuminance_level_sensing_updated_state_t illuminance_level_sensing_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + illuminance_level_sensing_new_state, + illuminance_level_sensing_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_illuminance_level_sensing_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_illuminance_level_sensing_force_read_attributes_callback) { + uic_mqtt_dotdot_illuminance_level_sensing_updated_state_t illuminance_level_sensing_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + illuminance_level_sensing_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for IlluminanceLevelSensing Cluster +void uic_mqtt_dotdot_illuminance_level_sensing_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_illuminance_level_sensing_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_illuminance_level_sensing_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IlluminanceLevelSensing/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/IlluminanceLevelSensing/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for IlluminanceLevelSensing Cluster +void uic_mqtt_dotdot_illuminance_level_sensing_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IlluminanceLevelSensing/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for TemperatureMeasurement Cluster +void uic_mqtt_dotdot_temperature_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/TemperatureMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for TemperatureMeasurement Cluster +void uic_mqtt_dotdot_temperature_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/TemperatureMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_temperature_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_temperature_measurement_write_attributes_callback) { + uic_mqtt_dotdot_temperature_measurement_state_t temperature_measurement_new_state = {}; + uic_mqtt_dotdot_temperature_measurement_updated_state_t temperature_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + temperature_measurement_new_state, + temperature_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_temperature_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_temperature_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_temperature_measurement_updated_state_t temperature_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + temperature_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for TemperatureMeasurement Cluster +void uic_mqtt_dotdot_temperature_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_temperature_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_temperature_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/TemperatureMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/TemperatureMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for TemperatureMeasurement Cluster +void uic_mqtt_dotdot_temperature_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/TemperatureMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for PressureMeasurement Cluster +void uic_mqtt_dotdot_pressure_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/PressureMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for PressureMeasurement Cluster +void uic_mqtt_dotdot_pressure_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/PressureMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_pressure_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_pressure_measurement_write_attributes_callback) { + uic_mqtt_dotdot_pressure_measurement_state_t pressure_measurement_new_state = {}; + uic_mqtt_dotdot_pressure_measurement_updated_state_t pressure_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + pressure_measurement_new_state, + pressure_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_pressure_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_pressure_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_pressure_measurement_updated_state_t pressure_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + pressure_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for PressureMeasurement Cluster +void uic_mqtt_dotdot_pressure_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_pressure_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_pressure_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/PressureMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/PressureMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for PressureMeasurement Cluster +void uic_mqtt_dotdot_pressure_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/PressureMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for FlowMeasurement Cluster +void uic_mqtt_dotdot_flow_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/FlowMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for FlowMeasurement Cluster +void uic_mqtt_dotdot_flow_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/FlowMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_flow_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_flow_measurement_write_attributes_callback) { + uic_mqtt_dotdot_flow_measurement_state_t flow_measurement_new_state = {}; + uic_mqtt_dotdot_flow_measurement_updated_state_t flow_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + flow_measurement_new_state, + flow_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_flow_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_flow_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_flow_measurement_updated_state_t flow_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + flow_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for FlowMeasurement Cluster +void uic_mqtt_dotdot_flow_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_flow_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_flow_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/FlowMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/FlowMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for FlowMeasurement Cluster +void uic_mqtt_dotdot_flow_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/FlowMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for RelativityHumidity Cluster +void uic_mqtt_dotdot_relativity_humidity_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/RelativityHumidity/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for RelativityHumidity Cluster +void uic_mqtt_dotdot_relativity_humidity_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/RelativityHumidity/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_relativity_humidity_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_relativity_humidity_write_attributes_callback) { + uic_mqtt_dotdot_relativity_humidity_state_t relativity_humidity_new_state = {}; + uic_mqtt_dotdot_relativity_humidity_updated_state_t relativity_humidity_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + relativity_humidity_new_state, + relativity_humidity_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_relativity_humidity_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_relativity_humidity_force_read_attributes_callback) { + uic_mqtt_dotdot_relativity_humidity_updated_state_t relativity_humidity_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + relativity_humidity_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for RelativityHumidity Cluster +void uic_mqtt_dotdot_relativity_humidity_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_relativity_humidity_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_relativity_humidity_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/RelativityHumidity/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/RelativityHumidity/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for RelativityHumidity Cluster +void uic_mqtt_dotdot_relativity_humidity_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/RelativityHumidity/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for OccupancySensing Cluster +void uic_mqtt_dotdot_occupancy_sensing_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/OccupancySensing/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for OccupancySensing Cluster +void uic_mqtt_dotdot_occupancy_sensing_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/OccupancySensing/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_occupancy_sensing_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_occupancy_sensing_write_attributes_callback) { + uic_mqtt_dotdot_occupancy_sensing_state_t occupancy_sensing_new_state = {}; + uic_mqtt_dotdot_occupancy_sensing_updated_state_t occupancy_sensing_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + occupancy_sensing_new_state, + occupancy_sensing_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_callback) { + uic_mqtt_dotdot_occupancy_sensing_updated_state_t occupancy_sensing_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + occupancy_sensing_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for OccupancySensing Cluster +void uic_mqtt_dotdot_occupancy_sensing_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_occupancy_sensing_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_occupancy_sensing_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/OccupancySensing/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/OccupancySensing/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for OccupancySensing Cluster +void uic_mqtt_dotdot_occupancy_sensing_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/OccupancySensing/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for SoilMoisture Cluster +void uic_mqtt_dotdot_soil_moisture_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/SoilMoisture/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for SoilMoisture Cluster +void uic_mqtt_dotdot_soil_moisture_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/SoilMoisture/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_soil_moisture_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_soil_moisture_write_attributes_callback) { + uic_mqtt_dotdot_soil_moisture_state_t soil_moisture_new_state = {}; + uic_mqtt_dotdot_soil_moisture_updated_state_t soil_moisture_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + soil_moisture_new_state, + soil_moisture_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_soil_moisture_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_soil_moisture_force_read_attributes_callback) { + uic_mqtt_dotdot_soil_moisture_updated_state_t soil_moisture_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + soil_moisture_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for SoilMoisture Cluster +void uic_mqtt_dotdot_soil_moisture_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_soil_moisture_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_soil_moisture_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/SoilMoisture/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/SoilMoisture/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for SoilMoisture Cluster +void uic_mqtt_dotdot_soil_moisture_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/SoilMoisture/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for PhMeasurement Cluster +void uic_mqtt_dotdot_ph_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/PhMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for PhMeasurement Cluster +void uic_mqtt_dotdot_ph_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/PhMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_ph_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ph_measurement_write_attributes_callback) { + uic_mqtt_dotdot_ph_measurement_state_t ph_measurement_new_state = {}; + uic_mqtt_dotdot_ph_measurement_updated_state_t ph_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ph_measurement_new_state, + ph_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_ph_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ph_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_ph_measurement_updated_state_t ph_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ph_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for PhMeasurement Cluster +void uic_mqtt_dotdot_ph_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_ph_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_ph_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/PhMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/PhMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for PhMeasurement Cluster +void uic_mqtt_dotdot_ph_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/PhMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for ElectricalConductivityMeasurement Cluster +void uic_mqtt_dotdot_electrical_conductivity_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/ElectricalConductivityMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for ElectricalConductivityMeasurement Cluster +void uic_mqtt_dotdot_electrical_conductivity_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/ElectricalConductivityMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_electrical_conductivity_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_electrical_conductivity_measurement_write_attributes_callback) { + uic_mqtt_dotdot_electrical_conductivity_measurement_state_t electrical_conductivity_measurement_new_state = {}; + uic_mqtt_dotdot_electrical_conductivity_measurement_updated_state_t electrical_conductivity_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + electrical_conductivity_measurement_new_state, + electrical_conductivity_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_electrical_conductivity_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_electrical_conductivity_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_electrical_conductivity_measurement_updated_state_t electrical_conductivity_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + electrical_conductivity_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ElectricalConductivityMeasurement Cluster +void uic_mqtt_dotdot_electrical_conductivity_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_electrical_conductivity_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_electrical_conductivity_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ElectricalConductivityMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/ElectricalConductivityMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ElectricalConductivityMeasurement Cluster +void uic_mqtt_dotdot_electrical_conductivity_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ElectricalConductivityMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for WindSpeedMeasurement Cluster +void uic_mqtt_dotdot_wind_speed_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/WindSpeedMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for WindSpeedMeasurement Cluster +void uic_mqtt_dotdot_wind_speed_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/WindSpeedMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_wind_speed_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_wind_speed_measurement_write_attributes_callback) { + uic_mqtt_dotdot_wind_speed_measurement_state_t wind_speed_measurement_new_state = {}; + uic_mqtt_dotdot_wind_speed_measurement_updated_state_t wind_speed_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + wind_speed_measurement_new_state, + wind_speed_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_wind_speed_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_wind_speed_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_wind_speed_measurement_updated_state_t wind_speed_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + wind_speed_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for WindSpeedMeasurement Cluster +void uic_mqtt_dotdot_wind_speed_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_wind_speed_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_wind_speed_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/WindSpeedMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/WindSpeedMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for WindSpeedMeasurement Cluster +void uic_mqtt_dotdot_wind_speed_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/WindSpeedMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for CarbonMonoxide Cluster +void uic_mqtt_dotdot_carbon_monoxide_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/CarbonMonoxide/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for CarbonMonoxide Cluster +void uic_mqtt_dotdot_carbon_monoxide_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/CarbonMonoxide/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_carbon_monoxide_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_carbon_monoxide_write_attributes_callback) { + uic_mqtt_dotdot_carbon_monoxide_state_t carbon_monoxide_new_state = {}; + uic_mqtt_dotdot_carbon_monoxide_updated_state_t carbon_monoxide_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + carbon_monoxide_new_state, + carbon_monoxide_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_carbon_monoxide_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_carbon_monoxide_force_read_attributes_callback) { + uic_mqtt_dotdot_carbon_monoxide_updated_state_t carbon_monoxide_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + carbon_monoxide_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for CarbonMonoxide Cluster +void uic_mqtt_dotdot_carbon_monoxide_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_carbon_monoxide_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_carbon_monoxide_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/CarbonMonoxide/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/CarbonMonoxide/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for CarbonMonoxide Cluster +void uic_mqtt_dotdot_carbon_monoxide_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/CarbonMonoxide/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for CarbonDioxide Cluster +void uic_mqtt_dotdot_carbon_dioxide_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/CarbonDioxide/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for CarbonDioxide Cluster +void uic_mqtt_dotdot_carbon_dioxide_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/CarbonDioxide/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_carbon_dioxide_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_carbon_dioxide_write_attributes_callback) { + uic_mqtt_dotdot_carbon_dioxide_state_t carbon_dioxide_new_state = {}; + uic_mqtt_dotdot_carbon_dioxide_updated_state_t carbon_dioxide_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + carbon_dioxide_new_state, + carbon_dioxide_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_carbon_dioxide_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_carbon_dioxide_force_read_attributes_callback) { + uic_mqtt_dotdot_carbon_dioxide_updated_state_t carbon_dioxide_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + carbon_dioxide_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for CarbonDioxide Cluster +void uic_mqtt_dotdot_carbon_dioxide_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_carbon_dioxide_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_carbon_dioxide_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/CarbonDioxide/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/CarbonDioxide/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for CarbonDioxide Cluster +void uic_mqtt_dotdot_carbon_dioxide_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/CarbonDioxide/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for PM25 Cluster +void uic_mqtt_dotdot_pm25_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/PM25/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for PM25 Cluster +void uic_mqtt_dotdot_pm25_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/PM25/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_pm25_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_pm25_write_attributes_callback) { + uic_mqtt_dotdot_pm25_state_t pm25_new_state = {}; + uic_mqtt_dotdot_pm25_updated_state_t pm25_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + pm25_new_state, + pm25_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_pm25_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_pm25_force_read_attributes_callback) { + uic_mqtt_dotdot_pm25_updated_state_t pm25_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + pm25_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for PM25 Cluster +void uic_mqtt_dotdot_pm25_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_pm25_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_pm25_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/PM25/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/PM25/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for PM25 Cluster +void uic_mqtt_dotdot_pm25_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/PM25/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for IASZone Cluster +void uic_mqtt_dotdot_ias_zone_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/IASZone/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for IASZone Cluster +void uic_mqtt_dotdot_ias_zone_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/IASZone/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_ias_zone_zone_enroll_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + ZoneEnrollResponseEnrollResponseCode enroll_response_code_value; + memset(&enroll_response_code_value, 0x00, sizeof(enroll_response_code_value)); + uint8_t zoneid_value; + memset(&zoneid_value, 0x00, sizeof(zoneid_value)); + for (const auto& callback: uic_mqtt_dotdot_ias_zone_zone_enroll_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + enroll_response_code_value, + + zoneid_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_ias_zone_zone_status_change_notification_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t zone_status_value; + memset(&zone_status_value, 0x00, sizeof(zone_status_value)); + uint8_t extended_status_value; + memset(&extended_status_value, 0x00, sizeof(extended_status_value)); + uint8_t zoneid_value; + memset(&zoneid_value, 0x00, sizeof(zoneid_value)); + uint16_t delay_value; + memset(&delay_value, 0x00, sizeof(delay_value)); + for (const auto& callback: uic_mqtt_dotdot_ias_zone_zone_status_change_notification_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + zone_status_value, + + extended_status_value, + + zoneid_value, + + delay_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_ias_zone_zone_enroll_request_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + IasZoneType zone_type_value; + memset(&zone_type_value, 0x00, sizeof(zone_type_value)); + uint16_t manufacturer_code_value; + memset(&manufacturer_code_value, 0x00, sizeof(manufacturer_code_value)); + for (const auto& callback: uic_mqtt_dotdot_ias_zone_zone_enroll_request_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + zone_type_value, + + manufacturer_code_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_ias_zone_initiate_test_mode_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t test_mode_duration_value; + memset(&test_mode_duration_value, 0x00, sizeof(test_mode_duration_value)); + uint8_t current_zone_sensitivity_level_value; + memset(¤t_zone_sensitivity_level_value, 0x00, sizeof(current_zone_sensitivity_level_value)); + for (const auto& callback: uic_mqtt_dotdot_ias_zone_initiate_test_mode_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + test_mode_duration_value, + + current_zone_sensitivity_level_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_ias_zone_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ias_zone_write_attributes_callback) { + uic_mqtt_dotdot_ias_zone_state_t ias_zone_new_state = {}; + uic_mqtt_dotdot_ias_zone_updated_state_t ias_zone_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ias_zone_new_state, + ias_zone_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_ias_zone_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_ias_zone_force_read_attributes_callback) { + uic_mqtt_dotdot_ias_zone_updated_state_t ias_zone_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + ias_zone_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for IASZone Cluster +void uic_mqtt_dotdot_ias_zone_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_ias_zone_zone_enroll_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ZoneEnrollResponse")"; + } + if (uic_mqtt_dotdot_ias_zone_zone_status_change_notification_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ZoneStatusChangeNotification")"; + } + if (uic_mqtt_dotdot_ias_zone_initiate_normal_operation_mode_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("InitiateNormalOperationMode")"; + } + if (uic_mqtt_dotdot_ias_zone_zone_enroll_request_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ZoneEnrollRequest")"; + } + if (uic_mqtt_dotdot_ias_zone_initiate_test_mode_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("InitiateTestMode")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_ias_zone_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_ias_zone_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IASZone/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/IASZone/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for IASZone Cluster +void uic_mqtt_dotdot_ias_zone_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IASZone/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for IASWD Cluster +void uic_mqtt_dotdot_iaswd_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/IASWD/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for IASWD Cluster +void uic_mqtt_dotdot_iaswd_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/IASWD/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_iaswd_start_warning_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t siren_configuration_value; + memset(&siren_configuration_value, 0x00, sizeof(siren_configuration_value)); + uint16_t warning_duration_value; + memset(&warning_duration_value, 0x00, sizeof(warning_duration_value)); + uint8_t strobe_duty_cycle_value; + memset(&strobe_duty_cycle_value, 0x00, sizeof(strobe_duty_cycle_value)); + IaswdLevel strobe_level_value; + memset(&strobe_level_value, 0x00, sizeof(strobe_level_value)); + for (const auto& callback: uic_mqtt_dotdot_iaswd_start_warning_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + siren_configuration_value, + + warning_duration_value, + + strobe_duty_cycle_value, + + strobe_level_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_iaswd_squawk_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t squawk_configuration_value; + memset(&squawk_configuration_value, 0x00, sizeof(squawk_configuration_value)); + for (const auto& callback: uic_mqtt_dotdot_iaswd_squawk_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + squawk_configuration_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_iaswd_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_iaswd_write_attributes_callback) { + uic_mqtt_dotdot_iaswd_state_t iaswd_new_state = {}; + uic_mqtt_dotdot_iaswd_updated_state_t iaswd_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + iaswd_new_state, + iaswd_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_iaswd_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_iaswd_force_read_attributes_callback) { + uic_mqtt_dotdot_iaswd_updated_state_t iaswd_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + iaswd_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for IASWD Cluster +void uic_mqtt_dotdot_iaswd_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_iaswd_start_warning_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("StartWarning")"; + } + if (uic_mqtt_dotdot_iaswd_squawk_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Squawk")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_iaswd_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_iaswd_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IASWD/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/IASWD/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for IASWD Cluster +void uic_mqtt_dotdot_iaswd_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/IASWD/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for Metering Cluster +void uic_mqtt_dotdot_metering_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/Metering/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for Metering Cluster +void uic_mqtt_dotdot_metering_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/Metering/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_metering_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_metering_write_attributes_callback) { + uic_mqtt_dotdot_metering_state_t metering_new_state = {}; + uic_mqtt_dotdot_metering_updated_state_t metering_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + metering_new_state, + metering_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_metering_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_metering_force_read_attributes_callback) { + uic_mqtt_dotdot_metering_updated_state_t metering_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + metering_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Metering Cluster +void uic_mqtt_dotdot_metering_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_metering_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_metering_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Metering/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/Metering/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for Metering Cluster +void uic_mqtt_dotdot_metering_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Metering/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for ElectricalMeasurement Cluster +void uic_mqtt_dotdot_electrical_measurement_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/ElectricalMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for ElectricalMeasurement Cluster +void uic_mqtt_dotdot_electrical_measurement_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/ElectricalMeasurement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_electrical_measurement_get_profile_info_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint8_t profile_count_value; + memset(&profile_count_value, 0x00, sizeof(profile_count_value)); + ProfileIntervalPeriod profile_interval_period_value; + memset(&profile_interval_period_value, 0x00, sizeof(profile_interval_period_value)); + uint8_t max_number_of_intervals_value; + memset(&max_number_of_intervals_value, 0x00, sizeof(max_number_of_intervals_value)); + for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_profile_info_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + profile_count_value, + + profile_interval_period_value, + + max_number_of_intervals_value, + + 0, nullptr + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_electrical_measurement_get_profile_info_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_profile_info_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_response_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + UTC start_time_value; + memset(&start_time_value, 0x00, sizeof(start_time_value)); + GetMeasurementProfileResponseStatus status_value; + memset(&status_value, 0x00, sizeof(status_value)); + ProfileIntervalPeriod profile_interval_period_value; + memset(&profile_interval_period_value, 0x00, sizeof(profile_interval_period_value)); + uint8_t number_of_intervals_delivered_value; + memset(&number_of_intervals_delivered_value, 0x00, sizeof(number_of_intervals_delivered_value)); + uint16_t attribute_id_value; + memset(&attribute_id_value, 0x00, sizeof(attribute_id_value)); + for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_response_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + start_time_value, + + status_value, + + profile_interval_period_value, + + number_of_intervals_delivered_value, + + attribute_id_value, + + 0, nullptr + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t attributeid_value; + memset(&attributeid_value, 0x00, sizeof(attributeid_value)); + UTC start_time_value; + memset(&start_time_value, 0x00, sizeof(start_time_value)); + uint8_t number_of_intervals_value; + memset(&number_of_intervals_value, 0x00, sizeof(number_of_intervals_value)); + for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + attributeid_value, + + start_time_value, + + number_of_intervals_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_electrical_measurement_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_write_attributes_callback) { + uic_mqtt_dotdot_electrical_measurement_state_t electrical_measurement_new_state = {}; + uic_mqtt_dotdot_electrical_measurement_updated_state_t electrical_measurement_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + electrical_measurement_new_state, + electrical_measurement_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_electrical_measurement_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_electrical_measurement_force_read_attributes_callback) { + uic_mqtt_dotdot_electrical_measurement_updated_state_t electrical_measurement_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + electrical_measurement_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ElectricalMeasurement Cluster +void uic_mqtt_dotdot_electrical_measurement_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_electrical_measurement_get_profile_info_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetProfileInfoResponse")"; + } + if (uic_mqtt_dotdot_electrical_measurement_get_profile_info_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetProfileInfo")"; + } + if (uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_response_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetMeasurementProfileResponse")"; + } + if (uic_mqtt_dotdot_electrical_measurement_get_measurement_profile_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetMeasurementProfile")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_electrical_measurement_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_electrical_measurement_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ElectricalMeasurement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/ElectricalMeasurement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ElectricalMeasurement Cluster +void uic_mqtt_dotdot_electrical_measurement_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ElectricalMeasurement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for Diagnostics Cluster +void uic_mqtt_dotdot_diagnostics_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/Diagnostics/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for Diagnostics Cluster +void uic_mqtt_dotdot_diagnostics_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/Diagnostics/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_diagnostics_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_diagnostics_write_attributes_callback) { + uic_mqtt_dotdot_diagnostics_state_t diagnostics_new_state = {}; + uic_mqtt_dotdot_diagnostics_updated_state_t diagnostics_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + diagnostics_new_state, + diagnostics_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_diagnostics_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_diagnostics_force_read_attributes_callback) { + uic_mqtt_dotdot_diagnostics_updated_state_t diagnostics_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + diagnostics_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Diagnostics Cluster +void uic_mqtt_dotdot_diagnostics_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_diagnostics_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_diagnostics_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Diagnostics/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/Diagnostics/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for Diagnostics Cluster +void uic_mqtt_dotdot_diagnostics_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Diagnostics/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for ProtocolController-RFTelemetry Cluster +void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/ProtocolController/RFTelemetry/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for ProtocolController-RFTelemetry Cluster +void uic_mqtt_dotdot_protocol_controller_rf_telemetry_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/ProtocolController/RFTelemetry/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_protocol_controller_rf_telemetry_tx_report_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* sourceunid_value; + memset(&sourceunid_value, 0x00, sizeof(sourceunid_value)); + const char* destinationunid_value; + memset(&destinationunid_value, 0x00, sizeof(destinationunid_value)); + bool transmission_successful_value; + memset(&transmission_successful_value, 0x00, sizeof(transmission_successful_value)); + uint16_t transmission_time_ms_value; + memset(&transmission_time_ms_value, 0x00, sizeof(transmission_time_ms_value)); + int8_t tx_powerd_bm_value; + memset(&tx_powerd_bm_value, 0x00, sizeof(tx_powerd_bm_value)); + uint8_t tx_channel_value; + memset(&tx_channel_value, 0x00, sizeof(tx_channel_value)); + uint8_t routing_attempts_value; + memset(&routing_attempts_value, 0x00, sizeof(routing_attempts_value)); + bool route_changed_value; + memset(&route_changed_value, 0x00, sizeof(route_changed_value)); + TxReportTransmissionSpeed transmission_speed_value; + memset(&transmission_speed_value, 0x00, sizeof(transmission_speed_value)); + int8_t measured_noise_floord_bm_value; + memset(&measured_noise_floord_bm_value, 0x00, sizeof(measured_noise_floord_bm_value)); + int8_t ackrssi_value; + memset(&ackrssi_value, 0x00, sizeof(ackrssi_value)); + uint8_t ack_channel_value; + memset(&ack_channel_value, 0x00, sizeof(ack_channel_value)); + const char* last_route_failed_link_functionalunid_value; + memset(&last_route_failed_link_functionalunid_value, 0x00, sizeof(last_route_failed_link_functionalunid_value)); + const char* last_route_failed_link_non_functionalunid_value; + memset(&last_route_failed_link_non_functionalunid_value, 0x00, sizeof(last_route_failed_link_non_functionalunid_value)); + int8_t destination_ack_tx_powerd_bm_value; + memset(&destination_ack_tx_powerd_bm_value, 0x00, sizeof(destination_ack_tx_powerd_bm_value)); + int8_t destination_ack_measuredrssi_value; + memset(&destination_ack_measuredrssi_value, 0x00, sizeof(destination_ack_measuredrssi_value)); + int8_t destination_ack_measured_noise_floor_value; + memset(&destination_ack_measured_noise_floor_value, 0x00, sizeof(destination_ack_measured_noise_floor_value)); + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_rf_telemetry_tx_report_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + sourceunid_value, + + destinationunid_value, + + transmission_successful_value, + + transmission_time_ms_value, + + tx_powerd_bm_value, + + tx_channel_value, + + routing_attempts_value, + + route_changed_value, + + transmission_speed_value, + + measured_noise_floord_bm_value, + + 0, nullptr, + + 0, nullptr, + + ackrssi_value, + + ack_channel_value, + + last_route_failed_link_functionalunid_value, + + last_route_failed_link_non_functionalunid_value, + + destination_ack_tx_powerd_bm_value, + + destination_ack_measuredrssi_value, + + destination_ack_measured_noise_floor_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_protocol_controller_rf_telemetry_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_rf_telemetry_write_attributes_callback) { + uic_mqtt_dotdot_protocol_controller_rf_telemetry_state_t protocol_controller_rf_telemetry_new_state = {}; + uic_mqtt_dotdot_protocol_controller_rf_telemetry_updated_state_t protocol_controller_rf_telemetry_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + protocol_controller_rf_telemetry_new_state, + protocol_controller_rf_telemetry_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_protocol_controller_rf_telemetry_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_rf_telemetry_force_read_attributes_callback) { + uic_mqtt_dotdot_protocol_controller_rf_telemetry_updated_state_t protocol_controller_rf_telemetry_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + protocol_controller_rf_telemetry_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ProtocolController-RFTelemetry Cluster +void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_protocol_controller_rf_telemetry_tx_report_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("TxReport")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_protocol_controller_rf_telemetry_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_protocol_controller_rf_telemetry_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + + topic += "/ProtocolController/RFTelemetry/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + + attributes_topic += "/ProtocolController/RFTelemetry/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ProtocolController-RFTelemetry Cluster +void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_empty_supported_commands( + const dotdot_unid_t unid + ) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ProtocolController/RFTelemetry/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for State Cluster +void uic_mqtt_dotdot_state_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/State/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for State Cluster +void uic_mqtt_dotdot_state_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/State/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_state_remove_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_remove_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_state_remove_offline_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_remove_offline_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_state_discover_neighbors_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_discover_neighbors_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_state_interview_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_interview_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_state_discover_security_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_discover_security_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_state_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_write_attributes_callback) { + uic_mqtt_dotdot_state_state_t state_new_state = {}; + uic_mqtt_dotdot_state_updated_state_t state_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + state_new_state, + state_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_state_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_state_force_read_attributes_callback) { + uic_mqtt_dotdot_state_updated_state_t state_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + state_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for State Cluster +void uic_mqtt_dotdot_state_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_state_remove_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Remove")"; + } + if (uic_mqtt_dotdot_state_remove_offline_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("RemoveOffline")"; + } + if (uic_mqtt_dotdot_state_discover_neighbors_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DiscoverNeighbors")"; + } + if (uic_mqtt_dotdot_state_interview_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Interview")"; + } + if (uic_mqtt_dotdot_state_discover_security_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DiscoverSecurity")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_state_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_state_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + + topic += "/State/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + + attributes_topic += "/State/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for State Cluster +void uic_mqtt_dotdot_state_publish_empty_supported_commands( + const dotdot_unid_t unid + ) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/State/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for Binding Cluster +void uic_mqtt_dotdot_binding_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/Binding/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for Binding Cluster +void uic_mqtt_dotdot_binding_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/Binding/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_binding_bind_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* cluster_name_value; + memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); + const char* destination_unid_value; + memset(&destination_unid_value, 0x00, sizeof(destination_unid_value)); + uint8_t destination_ep_value; + memset(&destination_ep_value, 0x00, sizeof(destination_ep_value)); + for (const auto& callback: uic_mqtt_dotdot_binding_bind_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + cluster_name_value, + + destination_unid_value, + + destination_ep_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_binding_unbind_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* cluster_name_value; + memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); + const char* destination_unid_value; + memset(&destination_unid_value, 0x00, sizeof(destination_unid_value)); + uint8_t destination_ep_value; + memset(&destination_ep_value, 0x00, sizeof(destination_ep_value)); + for (const auto& callback: uic_mqtt_dotdot_binding_unbind_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + cluster_name_value, + + destination_unid_value, + + destination_ep_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_binding_bind_to_protocol_controller_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* cluster_name_value; + memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); + for (const auto& callback: uic_mqtt_dotdot_binding_bind_to_protocol_controller_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + cluster_name_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_binding_unbind_from_protocol_controller_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* cluster_name_value; + memset(&cluster_name_value, 0x00, sizeof(cluster_name_value)); + for (const auto& callback: uic_mqtt_dotdot_binding_unbind_from_protocol_controller_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + cluster_name_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_binding_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_binding_write_attributes_callback) { + uic_mqtt_dotdot_binding_state_t binding_new_state = {}; + uic_mqtt_dotdot_binding_updated_state_t binding_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + binding_new_state, + binding_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_binding_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_binding_force_read_attributes_callback) { + uic_mqtt_dotdot_binding_updated_state_t binding_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + binding_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Binding Cluster +void uic_mqtt_dotdot_binding_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_binding_bind_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Bind")"; + } + if (uic_mqtt_dotdot_binding_unbind_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Unbind")"; + } + if (uic_mqtt_dotdot_binding_bind_to_protocol_controller_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("BindToProtocolController")"; + } + if (uic_mqtt_dotdot_binding_unbind_from_protocol_controller_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("UnbindFromProtocolController")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_binding_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_binding_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Binding/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/Binding/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for Binding Cluster +void uic_mqtt_dotdot_binding_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Binding/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for SystemMetrics Cluster +void uic_mqtt_dotdot_system_metrics_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/SystemMetrics/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for SystemMetrics Cluster +void uic_mqtt_dotdot_system_metrics_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/SystemMetrics/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_system_metrics_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_system_metrics_write_attributes_callback) { + uic_mqtt_dotdot_system_metrics_state_t system_metrics_new_state = {}; + uic_mqtt_dotdot_system_metrics_updated_state_t system_metrics_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + system_metrics_new_state, + system_metrics_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_system_metrics_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_system_metrics_force_read_attributes_callback) { + uic_mqtt_dotdot_system_metrics_updated_state_t system_metrics_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + system_metrics_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for SystemMetrics Cluster +void uic_mqtt_dotdot_system_metrics_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_system_metrics_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_system_metrics_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + + topic += "/SystemMetrics/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + + attributes_topic += "/SystemMetrics/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for SystemMetrics Cluster +void uic_mqtt_dotdot_system_metrics_publish_empty_supported_commands( + const dotdot_unid_t unid + ) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/SystemMetrics/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for ApplicationMonitoring Cluster +void uic_mqtt_dotdot_application_monitoring_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/ApplicationMonitoring/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for ApplicationMonitoring Cluster +void uic_mqtt_dotdot_application_monitoring_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/ApplicationMonitoring/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_application_monitoring_log_entry_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* timestamp_value; + memset(×tamp_value, 0x00, sizeof(timestamp_value)); + LoggingLevelEnum log_level_value; + memset(&log_level_value, 0x00, sizeof(log_level_value)); + const char* log_tag_value; + memset(&log_tag_value, 0x00, sizeof(log_tag_value)); + const char* log_message_value; + memset(&log_message_value, 0x00, sizeof(log_message_value)); + for (const auto& callback: uic_mqtt_dotdot_application_monitoring_log_entry_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + timestamp_value, + + log_level_value, + + log_tag_value, + + log_message_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_application_monitoring_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_application_monitoring_write_attributes_callback) { + uic_mqtt_dotdot_application_monitoring_state_t application_monitoring_new_state = {}; + uic_mqtt_dotdot_application_monitoring_updated_state_t application_monitoring_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + application_monitoring_new_state, + application_monitoring_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_application_monitoring_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_application_monitoring_force_read_attributes_callback) { + uic_mqtt_dotdot_application_monitoring_updated_state_t application_monitoring_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + application_monitoring_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ApplicationMonitoring Cluster +void uic_mqtt_dotdot_application_monitoring_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_application_monitoring_log_entry_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("LogEntry")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_application_monitoring_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_application_monitoring_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + + topic += "/ApplicationMonitoring/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + + attributes_topic += "/ApplicationMonitoring/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ApplicationMonitoring Cluster +void uic_mqtt_dotdot_application_monitoring_publish_empty_supported_commands( + const dotdot_unid_t unid + ) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ApplicationMonitoring/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for NameAndLocation Cluster +void uic_mqtt_dotdot_name_and_location_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/NameAndLocation/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for NameAndLocation Cluster +void uic_mqtt_dotdot_name_and_location_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/NameAndLocation/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_name_and_location_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_name_and_location_write_attributes_callback) { + uic_mqtt_dotdot_name_and_location_state_t name_and_location_new_state = {}; + uic_mqtt_dotdot_name_and_location_updated_state_t name_and_location_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + name_and_location_new_state, + name_and_location_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_name_and_location_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_name_and_location_force_read_attributes_callback) { + uic_mqtt_dotdot_name_and_location_updated_state_t name_and_location_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + name_and_location_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for NameAndLocation Cluster +void uic_mqtt_dotdot_name_and_location_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_name_and_location_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_name_and_location_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/NameAndLocation/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/NameAndLocation/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for NameAndLocation Cluster +void uic_mqtt_dotdot_name_and_location_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/NameAndLocation/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for ConfigurationParameters Cluster +void uic_mqtt_dotdot_configuration_parameters_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/ConfigurationParameters/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for ConfigurationParameters Cluster +void uic_mqtt_dotdot_configuration_parameters_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/ConfigurationParameters/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_configuration_parameters_discover_parameter_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t parameter_id_value; + memset(¶meter_id_value, 0x00, sizeof(parameter_id_value)); + for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_discover_parameter_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + parameter_id_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_configuration_parameters_set_parameter_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t parameter_id_value; + memset(¶meter_id_value, 0x00, sizeof(parameter_id_value)); + int64_t value_value; + memset(&value_value, 0x00, sizeof(value_value)); + for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_set_parameter_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + parameter_id_value, + + value_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t first_parameter_id_value; + memset(&first_parameter_id_value, 0x00, sizeof(first_parameter_id_value)); + uint16_t last_parameter_id_value; + memset(&last_parameter_id_value, 0x00, sizeof(last_parameter_id_value)); + for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + first_parameter_id_value, + + last_parameter_id_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_configuration_parameters_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_write_attributes_callback) { + uic_mqtt_dotdot_configuration_parameters_state_t configuration_parameters_new_state = {}; + uic_mqtt_dotdot_configuration_parameters_updated_state_t configuration_parameters_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + configuration_parameters_new_state, + configuration_parameters_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_configuration_parameters_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_configuration_parameters_force_read_attributes_callback) { + uic_mqtt_dotdot_configuration_parameters_updated_state_t configuration_parameters_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + configuration_parameters_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ConfigurationParameters Cluster +void uic_mqtt_dotdot_configuration_parameters_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_configuration_parameters_discover_parameter_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DiscoverParameter")"; + } + if (uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DefaultResetAllParameters")"; + } + if (uic_mqtt_dotdot_configuration_parameters_set_parameter_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetParameter")"; + } + if (uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DiscoverParameterRange")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_configuration_parameters_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_configuration_parameters_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ConfigurationParameters/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/ConfigurationParameters/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ConfigurationParameters Cluster +void uic_mqtt_dotdot_configuration_parameters_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/ConfigurationParameters/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for UserCredential Cluster +void uic_mqtt_dotdot_user_credential_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/UserCredential/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for UserCredential Cluster +void uic_mqtt_dotdot_user_credential_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/UserCredential/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_user_credential_add_user_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + UserTypeEnum user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + bool user_active_state_value; + memset(&user_active_state_value, 0x00, sizeof(user_active_state_value)); + CredRule credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint16_t expiring_timeout_minutes_value; + memset(&expiring_timeout_minutes_value, 0x00, sizeof(expiring_timeout_minutes_value)); + UserNameEncodingType user_name_encoding_value; + memset(&user_name_encoding_value, 0x00, sizeof(user_name_encoding_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_add_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + user_type_value, + + user_active_state_value, + + credential_rule_value, + + user_name_value, + + expiring_timeout_minutes_value, + + user_name_encoding_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_modify_user_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + UserTypeEnum user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + bool user_active_state_value; + memset(&user_active_state_value, 0x00, sizeof(user_active_state_value)); + CredRule credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint16_t expiring_timeout_minutes_value; + memset(&expiring_timeout_minutes_value, 0x00, sizeof(expiring_timeout_minutes_value)); + UserNameEncodingType user_name_encoding_value; + memset(&user_name_encoding_value, 0x00, sizeof(user_name_encoding_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_modify_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + user_type_value, + + user_active_state_value, + + credential_rule_value, + + user_name_value, + + expiring_timeout_minutes_value, + + user_name_encoding_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_user_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_add_credential_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_add_credential_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_data_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_modify_credential_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_modify_credential_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_data_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_credential_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_credential_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_all_users_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_users_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_all_credentials_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_credential_learn_start_add_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + uint8_t credential_learn_timeout_value; + memset(&credential_learn_timeout_value, 0x00, sizeof(credential_learn_timeout_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_learn_timeout_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_credential_learn_start_modify_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + uint8_t credential_learn_timeout_value; + memset(&credential_learn_timeout_value, 0x00, sizeof(credential_learn_timeout_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_learn_timeout_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_credential_learn_stop_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_learn_stop_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_credential_association_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t source_user_uniqueid_value; + memset(&source_user_uniqueid_value, 0x00, sizeof(source_user_uniqueid_value)); + uint16_t source_credential_slot_value; + memset(&source_credential_slot_value, 0x00, sizeof(source_credential_slot_value)); + uint16_t destination_user_uniqueid_value; + memset(&destination_user_uniqueid_value, 0x00, sizeof(destination_user_uniqueid_value)); + uint16_t destination_credential_slot_value; + memset(&destination_credential_slot_value, 0x00, sizeof(destination_credential_slot_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_credential_association_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value, + + source_user_uniqueid_value, + + source_credential_slot_value, + + destination_user_uniqueid_value, + + destination_credential_slot_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_get_user_checksum_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_get_user_checksum_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_get_credential_checksum_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_get_credential_checksum_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_get_all_users_checksum_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_set_admin_pin_code_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* pin_code_value; + memset(&pin_code_value, 0x00, sizeof(pin_code_value)); + for (const auto& callback: uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + pin_code_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_user_credential_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_write_attributes_callback) { + uic_mqtt_dotdot_user_credential_state_t user_credential_new_state = {}; + uic_mqtt_dotdot_user_credential_updated_state_t user_credential_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_credential_new_state, + user_credential_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_user_credential_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_user_credential_force_read_attributes_callback) { + uic_mqtt_dotdot_user_credential_updated_state_t user_credential_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + user_credential_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for UserCredential Cluster +void uic_mqtt_dotdot_user_credential_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_user_credential_add_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("AddUser")"; + } + if (uic_mqtt_dotdot_user_credential_modify_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ModifyUser")"; + } + if (uic_mqtt_dotdot_user_credential_delete_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteUser")"; + } + if (uic_mqtt_dotdot_user_credential_add_credential_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("AddCredential")"; + } + if (uic_mqtt_dotdot_user_credential_modify_credential_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ModifyCredential")"; + } + if (uic_mqtt_dotdot_user_credential_delete_credential_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteCredential")"; + } + if (uic_mqtt_dotdot_user_credential_delete_all_users_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteAllUsers")"; + } + if (uic_mqtt_dotdot_user_credential_delete_all_credentials_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteAllCredentials")"; + } + if (uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteAllCredentialsByType")"; + } + if (uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteAllCredentialsForUser")"; + } + if (uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeleteAllCredentialsForUserByType")"; + } + if (uic_mqtt_dotdot_user_credential_credential_learn_start_add_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("CredentialLearnStartAdd")"; + } + if (uic_mqtt_dotdot_user_credential_credential_learn_start_modify_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("CredentialLearnStartModify")"; + } + if (uic_mqtt_dotdot_user_credential_credential_learn_stop_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("CredentialLearnStop")"; + } + if (uic_mqtt_dotdot_user_credential_credential_association_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("CredentialAssociation")"; + } + if (uic_mqtt_dotdot_user_credential_get_user_checksum_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetUserChecksum")"; + } + if (uic_mqtt_dotdot_user_credential_get_credential_checksum_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetCredentialChecksum")"; + } + if (uic_mqtt_dotdot_user_credential_get_all_users_checksum_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("GetAllUsersChecksum")"; + } + if (uic_mqtt_dotdot_user_credential_set_admin_pin_code_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetAdminPINCode")"; + } + if (uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("DeactivateAdminPINCode")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_user_credential_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_user_credential_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UserCredential/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/UserCredential/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for UserCredential Cluster +void uic_mqtt_dotdot_user_credential_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UserCredential/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for AoXLocator Cluster +void uic_mqtt_dotdot_aox_locator_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/AoXLocator/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for AoXLocator Cluster +void uic_mqtt_dotdot_aox_locator_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/AoXLocator/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_aox_locator_iq_report_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* tag_unid_value; + memset(&tag_unid_value, 0x00, sizeof(tag_unid_value)); + uint8_t channel_value; + memset(&channel_value, 0x00, sizeof(channel_value)); + int8_t rssi_value; + memset(&rssi_value, 0x00, sizeof(rssi_value)); + int32_t sequence_value; + memset(&sequence_value, 0x00, sizeof(sequence_value)); + for (const auto& callback: uic_mqtt_dotdot_aox_locator_iq_report_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + tag_unid_value, + + channel_value, + + rssi_value, + + 0, nullptr, + + sequence_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_aox_locator_angle_report_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* tag_unid_value; + memset(&tag_unid_value, 0x00, sizeof(tag_unid_value)); + SphericalCoordinates direction_value; + memset(&direction_value, 0x00, sizeof(direction_value)); + SphericalCoordinates deviation_value; + memset(&deviation_value, 0x00, sizeof(deviation_value)); + int32_t sequence_value; + memset(&sequence_value, 0x00, sizeof(sequence_value)); + for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_report_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + tag_unid_value, + + direction_value, + + deviation_value, + + sequence_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_aox_locator_angle_correction_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + const char* tag_unid_value; + memset(&tag_unid_value, 0x00, sizeof(tag_unid_value)); + SphericalCoordinates direction_value; + memset(&direction_value, 0x00, sizeof(direction_value)); + SphericalCoordinates deviation_value; + memset(&deviation_value, 0x00, sizeof(deviation_value)); + int32_t sequence_value; + memset(&sequence_value, 0x00, sizeof(sequence_value)); + for (const auto& callback: uic_mqtt_dotdot_aox_locator_angle_correction_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + tag_unid_value, + + direction_value, + + deviation_value, + + sequence_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_aox_locator_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_aox_locator_write_attributes_callback) { + uic_mqtt_dotdot_aox_locator_state_t aox_locator_new_state = {}; + uic_mqtt_dotdot_aox_locator_updated_state_t aox_locator_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + aox_locator_new_state, + aox_locator_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_aox_locator_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_aox_locator_force_read_attributes_callback) { + uic_mqtt_dotdot_aox_locator_updated_state_t aox_locator_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + aox_locator_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for AoXLocator Cluster +void uic_mqtt_dotdot_aox_locator_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_aox_locator_iq_report_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("IQReport")"; + } + if (uic_mqtt_dotdot_aox_locator_angle_report_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("AngleReport")"; + } + if (uic_mqtt_dotdot_aox_locator_angle_correction_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("AngleCorrection")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_aox_locator_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_aox_locator_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/AoXLocator/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/AoXLocator/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for AoXLocator Cluster +void uic_mqtt_dotdot_aox_locator_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/AoXLocator/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for AoXPositionEstimation Cluster +void uic_mqtt_dotdot_aox_position_estimation_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/AoXPositionEstimation/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for AoXPositionEstimation Cluster +void uic_mqtt_dotdot_aox_position_estimation_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/AoXPositionEstimation/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_aox_position_estimation_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_write_attributes_callback) { + uic_mqtt_dotdot_aox_position_estimation_state_t aox_position_estimation_new_state = {}; + uic_mqtt_dotdot_aox_position_estimation_updated_state_t aox_position_estimation_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + aox_position_estimation_new_state, + aox_position_estimation_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback) { + uic_mqtt_dotdot_aox_position_estimation_updated_state_t aox_position_estimation_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + aox_position_estimation_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for AoXPositionEstimation Cluster +void uic_mqtt_dotdot_aox_position_estimation_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_aox_position_estimation_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/AoXPositionEstimation/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/AoXPositionEstimation/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for AoXPositionEstimation Cluster +void uic_mqtt_dotdot_aox_position_estimation_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/AoXPositionEstimation/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for ProtocolController-NetworkManagement Cluster +void uic_mqtt_dotdot_protocol_controller_network_management_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/ProtocolController/NetworkManagement/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for ProtocolController-NetworkManagement Cluster +void uic_mqtt_dotdot_protocol_controller_network_management_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/ProtocolController/NetworkManagement/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_protocol_controller_network_management_write_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_callback) { + uic_mqtt_dotdot_protocol_controller_network_management_state_t protocol_controller_network_management_new_state = {}; + uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t protocol_controller_network_management_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + protocol_controller_network_management_new_state, + protocol_controller_network_management_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_callback) { + uic_mqtt_dotdot_protocol_controller_network_management_updated_state_t protocol_controller_network_management_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + protocol_controller_network_management_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for ProtocolController-NetworkManagement Cluster +void uic_mqtt_dotdot_protocol_controller_network_management_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_protocol_controller_network_management_write_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("Write")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_protocol_controller_network_management_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_protocol_controller_network_management_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + + topic += "/ProtocolController/NetworkManagement/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + + attributes_topic += "/ProtocolController/NetworkManagement/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for ProtocolController-NetworkManagement Cluster +void uic_mqtt_dotdot_protocol_controller_network_management_publish_empty_supported_commands( + const dotdot_unid_t unid + ) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ProtocolController/NetworkManagement/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for Descriptor Cluster +void uic_mqtt_dotdot_descriptor_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/Descriptor/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for Descriptor Cluster +void uic_mqtt_dotdot_descriptor_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/Descriptor/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_descriptor_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_descriptor_write_attributes_callback) { + uic_mqtt_dotdot_descriptor_state_t descriptor_new_state = {}; + uic_mqtt_dotdot_descriptor_updated_state_t descriptor_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + descriptor_new_state, + descriptor_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_descriptor_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_descriptor_force_read_attributes_callback) { + uic_mqtt_dotdot_descriptor_updated_state_t descriptor_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + descriptor_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for Descriptor Cluster +void uic_mqtt_dotdot_descriptor_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_descriptor_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_descriptor_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Descriptor/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/Descriptor/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for Descriptor Cluster +void uic_mqtt_dotdot_descriptor_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/Descriptor/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for UnifyFanControl Cluster +void uic_mqtt_dotdot_unify_fan_control_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/UnifyFanControl/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for UnifyFanControl Cluster +void uic_mqtt_dotdot_unify_fan_control_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/UnifyFanControl/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_unify_fan_control_set_fan_mode_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + ZWaveFanModeEnum fan_mode_value; + memset(&fan_mode_value, 0x00, sizeof(fan_mode_value)); + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_set_fan_mode_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + fan_mode_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_unify_fan_control_turn_off_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_turn_off_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_unify_fan_control_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_write_attributes_callback) { + uic_mqtt_dotdot_unify_fan_control_state_t unify_fan_control_new_state = {}; + uic_mqtt_dotdot_unify_fan_control_updated_state_t unify_fan_control_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_fan_control_new_state, + unify_fan_control_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_unify_fan_control_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_fan_control_force_read_attributes_callback) { + uic_mqtt_dotdot_unify_fan_control_updated_state_t unify_fan_control_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_fan_control_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for UnifyFanControl Cluster +void uic_mqtt_dotdot_unify_fan_control_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_unify_fan_control_set_fan_mode_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetFanMode")"; + } + if (uic_mqtt_dotdot_unify_fan_control_turn_off_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("TurnOff")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_unify_fan_control_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_unify_fan_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyFanControl/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/UnifyFanControl/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for UnifyFanControl Cluster +void uic_mqtt_dotdot_unify_fan_control_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyFanControl/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/UnifyThermostat/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/UnifyThermostat/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + + +static inline bool uic_mqtt_dotdot_unify_thermostat_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_write_attributes_callback) { + uic_mqtt_dotdot_unify_thermostat_state_t unify_thermostat_new_state = {}; + uic_mqtt_dotdot_unify_thermostat_updated_state_t unify_thermostat_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_thermostat_new_state, + unify_thermostat_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_unify_thermostat_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_thermostat_force_read_attributes_callback) { + uic_mqtt_dotdot_unify_thermostat_updated_state_t unify_thermostat_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_thermostat_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_unify_thermostat_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_unify_thermostat_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyThermostat/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/UnifyThermostat/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for UnifyThermostat Cluster +void uic_mqtt_dotdot_unify_thermostat_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyThermostat/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + +// Publishing Cluster Revision for UnifyHumidityControl Cluster +void uic_mqtt_dotdot_unify_humidity_control_publish_cluster_revision(const char* base_topic, uint16_t value) +{ + std::string cluster_topic = std::string(base_topic) + "/UnifyHumidityControl/Attributes/ClusterRevision"; + // Publish Desired + std::string pub_topic_des = cluster_topic + "/Desired"; + std::string payload = std::string(R"({"value": )") + + std::to_string(value) + std::string("}"); + uic_mqtt_publish(pub_topic_des.c_str(), + payload.c_str(), + payload.size(), + true); + // Publish Reported + std::string pub_topic_rep = cluster_topic + "/Reported"; + uic_mqtt_publish(pub_topic_rep.c_str(), + payload.c_str(), + payload.size(), + true); +} + +// Unretain Cluster Revision for UnifyHumidityControl Cluster +void uic_mqtt_dotdot_unify_humidity_control_unretain_cluster_revision(const char* base_topic) +{ + // clang-format on + std::string cluster_topic + = std::string(base_topic) + + "/UnifyHumidityControl/Attributes/ClusterRevision"; + // Publish Desired + std::string desired_topic = cluster_topic + "/Desired"; + uic_mqtt_publish(desired_topic.c_str(), NULL, 0, true); + // Publish Reported + std::string reported_topic = cluster_topic + "/Reported"; + uic_mqtt_publish(reported_topic.c_str(), NULL, 0, true); + // clang-format off +} + +static inline bool uic_mqtt_dotdot_unify_humidity_control_mode_set_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + ModeType mode_value; + memset(&mode_value, 0x00, sizeof(mode_value)); + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_mode_set_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + mode_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} +static inline bool uic_mqtt_dotdot_unify_humidity_control_setpoint_set_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + SetpointType type_value; + memset(&type_value, 0x00, sizeof(type_value)); + uint8_t precision_value; + memset(&precision_value, 0x00, sizeof(precision_value)); + uint8_t scale_value; + memset(&scale_value, 0x00, sizeof(scale_value)); + int32_t value_value; + memset(&value_value, 0x00, sizeof(value_value)); + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_setpoint_set_callback) { + if (callback( unid, endpoint_id, UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + type_value, + + precision_value, + + scale_value, + + value_value + + ) == SL_STATUS_OK) { + return true; + } + } + + return false; +} + +static inline bool uic_mqtt_dotdot_unify_humidity_control_write_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_write_attributes_callback) { + uic_mqtt_dotdot_unify_humidity_control_state_t unify_humidity_control_new_state = {}; + uic_mqtt_dotdot_unify_humidity_control_updated_state_t unify_humidity_control_new_updated_state = {}; + + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_humidity_control_new_state, + unify_humidity_control_new_updated_state + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +static inline bool uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_is_supported( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + for (const auto& callback: uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_callback) { + uic_mqtt_dotdot_unify_humidity_control_updated_state_t unify_humidity_control_force_update = {0}; + if (callback( + unid, + endpoint_id, + UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK, + unify_humidity_control_force_update + ) == SL_STATUS_OK) { + return true; + } + } + return false; +} + +// Publishing Supported Commands for UnifyHumidityControl Cluster +void uic_mqtt_dotdot_unify_humidity_control_publish_supported_commands( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id) +{ + std::stringstream ss; + bool first_command = true; + ss.str(""); + + // check if there is callback for each command + if (uic_mqtt_dotdot_unify_humidity_control_mode_set_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ModeSet")"; + } + if (uic_mqtt_dotdot_unify_humidity_control_setpoint_set_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("SetpointSet")"; + } + + // Check for a WriteAttributes Callback + if(uic_mqtt_dotdot_unify_humidity_control_write_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("WriteAttributes")"; + } + + // Check for a ForceReadAttributes Callback + if (uic_mqtt_dotdot_unify_humidity_control_force_read_attributes_is_supported(unid, endpoint_id)) { + if (first_command == false) { + ss << ", "; + } + first_command = false; + ss << R"("ForceReadAttributes")"; + } + + // Publish supported commands + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyHumidityControl/SupportedCommands"; + std::string payload_str("{\"value\": [" + ss.str() + "]" + "}"); + if (first_command == false) { + uic_mqtt_publish(topic.c_str(), + payload_str.c_str(), + payload_str.length(), + true); + } else if (uic_mqtt_count_topics(topic.c_str()) == 0) { + // There are no supported commands, but make sure we publish some + // SupportedCommands = [] if any attribute has been published for a cluster. + std::string attributes_topic = "ucl/by-unid/" + std::string(unid); + attributes_topic += "/ep"+ std::to_string(endpoint_id); + attributes_topic += "/UnifyHumidityControl/Attributes"; + + if (uic_mqtt_count_topics(attributes_topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } + } +} + +// Publishing empty/no Supported Commands for UnifyHumidityControl Cluster +void uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands( + const dotdot_unid_t unid + , dotdot_endpoint_id_t endpoint_id) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint_id); + topic += "/UnifyHumidityControl/SupportedCommands"; + + if (uic_mqtt_count_topics(topic.c_str()) > 0) { + uic_mqtt_publish(topic.c_str(), + EMPTY_VALUE_ARRAY, + strlen(EMPTY_VALUE_ARRAY), + true); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Generated Commands publications functions +//////////////////////////////////////////////////////////////////////////////// +/** + * @brief Publishes an incoming/generated ResetToFactoryDefaults command for + * the Basic cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Basic/GeneratedCommands/ResetToFactoryDefaults + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_basic_publish_generated_reset_to_factory_defaults_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Basic/GeneratedCommands/ResetToFactoryDefaults"; + + std::string payload = + get_json_payload_for_basic_reset_to_factory_defaults_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated Identify command for + * the Identify cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/Identify + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_identify_publish_generated_identify_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_identify_command_identify_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Identify/GeneratedCommands/Identify"; + + std::string payload = + get_json_payload_for_identify_identify_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated IdentifyQueryResponse command for + * the Identify cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/IdentifyQueryResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_identify_publish_generated_identify_query_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_identify_command_identify_query_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Identify/GeneratedCommands/IdentifyQueryResponse"; + + std::string payload = + get_json_payload_for_identify_identify_query_response_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated IdentifyQuery command for + * the Identify cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/IdentifyQuery + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_identify_publish_generated_identify_query_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Identify/GeneratedCommands/IdentifyQuery"; + + std::string payload = + get_json_payload_for_identify_identify_query_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated TriggerEffect command for + * the Identify cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/TriggerEffect + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_identify_publish_generated_trigger_effect_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_identify_command_trigger_effect_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Identify/GeneratedCommands/TriggerEffect"; + + std::string payload = + get_json_payload_for_identify_trigger_effect_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated AddGroup command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/AddGroup + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_add_group_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_add_group_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/AddGroup"; + + std::string payload = + get_json_payload_for_groups_add_group_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated AddGroupResponse command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/AddGroupResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_add_group_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_add_group_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/AddGroupResponse"; + + std::string payload = + get_json_payload_for_groups_add_group_response_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated ViewGroup command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/ViewGroup + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_view_group_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_view_group_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/ViewGroup"; + + std::string payload = + get_json_payload_for_groups_view_group_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated ViewGroupResponse command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/ViewGroupResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_view_group_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_view_group_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/ViewGroupResponse"; + + std::string payload = + get_json_payload_for_groups_view_group_response_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated GetGroupMembership command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/GetGroupMembership + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_get_group_membership_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/GetGroupMembership"; + + std::string payload = + get_json_payload_for_groups_get_group_membership_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated GetGroupMembershipResponse command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/GetGroupMembershipResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_get_group_membership_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/GetGroupMembershipResponse"; + + std::string payload = + get_json_payload_for_groups_get_group_membership_response_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated RemoveGroup command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/RemoveGroup + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_remove_group_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_remove_group_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/RemoveGroup"; + + std::string payload = + get_json_payload_for_groups_remove_group_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated RemoveGroupResponse command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/RemoveGroupResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_remove_group_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_remove_group_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/RemoveGroupResponse"; + + std::string payload = + get_json_payload_for_groups_remove_group_response_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated RemoveAllGroups command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/RemoveAllGroups + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_groups_publish_generated_remove_all_groups_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/RemoveAllGroups"; + + std::string payload = + get_json_payload_for_groups_remove_all_groups_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated AddGroupIfIdentifying command for + * the Groups cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/AddGroupIfIdentifying + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_groups_publish_generated_add_group_if_identifying_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_groups_command_add_group_if_identifying_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Groups/GeneratedCommands/AddGroupIfIdentifying"; + + std::string payload = + get_json_payload_for_groups_add_group_if_identifying_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated AddScene command for + * the Scenes cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/AddScene + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_scenes_publish_generated_add_scene_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_add_scene_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Scenes/GeneratedCommands/AddScene"; + + std::string payload = + get_json_payload_for_scenes_add_scene_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated AddSceneResponse command for + * the Scenes cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/AddSceneResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_scenes_publish_generated_add_scene_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_add_scene_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Scenes/GeneratedCommands/AddSceneResponse"; + + std::string payload = + get_json_payload_for_scenes_add_scene_response_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated ViewScene command for + * the Scenes cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/ViewScene + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_scenes_publish_generated_view_scene_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_view_scene_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Scenes/GeneratedCommands/ViewScene"; + + std::string payload = + get_json_payload_for_scenes_view_scene_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated ViewSceneResponse command for + * the Scenes cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/ViewSceneResponse + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_scenes_publish_generated_view_scene_response_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_view_scene_response_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Scenes/GeneratedCommands/ViewSceneResponse"; -// Publishing empty/no Supported Commands for UnifyHumidityControl Cluster -void uic_mqtt_dotdot_unify_humidity_control_publish_empty_supported_commands( - const dotdot_unid_t unid - , dotdot_endpoint_id_t endpoint_id) -{ - std::string topic = "ucl/by-unid/" + std::string(unid); - topic += "/ep"+ std::to_string(endpoint_id); - topic += "/UnifyHumidityControl/SupportedCommands"; + std::string payload = + get_json_payload_for_scenes_view_scene_response_command( + fields); - if (uic_mqtt_count_topics(topic.c_str()) > 0) { - uic_mqtt_publish(topic.c_str(), - EMPTY_VALUE_ARRAY, - strlen(EMPTY_VALUE_ARRAY), - true); - } + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); } +/** + * @brief Publishes an incoming/generated RemoveScene command for + * the Scenes cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveScene + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_remove_scene_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "Scenes/GeneratedCommands/RemoveScene"; + std::string payload = + get_json_payload_for_scenes_remove_scene_command( + fields); -//////////////////////////////////////////////////////////////////////////////// -// Generated Commands publications functions -//////////////////////////////////////////////////////////////////////////////// + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} /** - * @brief Publishes an incoming/generated ResetToFactoryDefaults command for - * the Basic cluster. + * @brief Publishes an incoming/generated RemoveSceneResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Basic/GeneratedCommands/ResetToFactoryDefaults + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveSceneResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_basic_publish_generated_reset_to_factory_defaults_command( +void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_remove_scene_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Basic/GeneratedCommands/ResetToFactoryDefaults"; + topic += "Scenes/GeneratedCommands/RemoveSceneResponse"; std::string payload = - get_json_payload_for_basic_reset_to_factory_defaults_command( - ); + get_json_payload_for_scenes_remove_scene_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112186,11 +117883,11 @@ void uic_mqtt_dotdot_basic_publish_generated_reset_to_factory_defaults_command( false); } /** - * @brief Publishes an incoming/generated Identify command for - * the Identify cluster. + * @brief Publishes an incoming/generated RemoveAllScenes command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/Identify + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveAllScenes * * @param unid The UNID of the node that sent us the command. * @@ -112200,19 +117897,19 @@ void uic_mqtt_dotdot_basic_publish_generated_reset_to_factory_defaults_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_identify_publish_generated_identify_command( +void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_identify_command_identify_fields_t *fields + const uic_mqtt_dotdot_scenes_command_remove_all_scenes_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Identify/GeneratedCommands/Identify"; + topic += "Scenes/GeneratedCommands/RemoveAllScenes"; std::string payload = - get_json_payload_for_identify_identify_command( + get_json_payload_for_scenes_remove_all_scenes_command( fields); // Publish our command @@ -112222,11 +117919,11 @@ void uic_mqtt_dotdot_identify_publish_generated_identify_command( false); } /** - * @brief Publishes an incoming/generated IdentifyQueryResponse command for - * the Identify cluster. + * @brief Publishes an incoming/generated RemoveAllScenesResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/IdentifyQueryResponse + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveAllScenesResponse * * @param unid The UNID of the node that sent us the command. * @@ -112236,19 +117933,19 @@ void uic_mqtt_dotdot_identify_publish_generated_identify_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_identify_publish_generated_identify_query_response_command( +void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_identify_command_identify_query_response_fields_t *fields + const uic_mqtt_dotdot_scenes_command_remove_all_scenes_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Identify/GeneratedCommands/IdentifyQueryResponse"; + topic += "Scenes/GeneratedCommands/RemoveAllScenesResponse"; std::string payload = - get_json_payload_for_identify_identify_query_response_command( + get_json_payload_for_scenes_remove_all_scenes_response_command( fields); // Publish our command @@ -112258,30 +117955,34 @@ void uic_mqtt_dotdot_identify_publish_generated_identify_query_response_command( false); } /** - * @brief Publishes an incoming/generated IdentifyQuery command for - * the Identify cluster. + * @brief Publishes an incoming/generated StoreScene command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/IdentifyQuery + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/StoreScene * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_identify_publish_generated_identify_query_command( +void uic_mqtt_dotdot_scenes_publish_generated_store_scene_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_store_scene_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Identify/GeneratedCommands/IdentifyQuery"; + topic += "Scenes/GeneratedCommands/StoreScene"; std::string payload = - get_json_payload_for_identify_identify_query_command( - ); + get_json_payload_for_scenes_store_scene_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112290,11 +117991,11 @@ void uic_mqtt_dotdot_identify_publish_generated_identify_query_command( false); } /** - * @brief Publishes an incoming/generated TriggerEffect command for - * the Identify cluster. + * @brief Publishes an incoming/generated StoreSceneResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Identify/GeneratedCommands/TriggerEffect + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/StoreSceneResponse * * @param unid The UNID of the node that sent us the command. * @@ -112304,19 +118005,19 @@ void uic_mqtt_dotdot_identify_publish_generated_identify_query_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_identify_publish_generated_trigger_effect_command( +void uic_mqtt_dotdot_scenes_publish_generated_store_scene_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_identify_command_trigger_effect_fields_t *fields + const uic_mqtt_dotdot_scenes_command_store_scene_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Identify/GeneratedCommands/TriggerEffect"; + topic += "Scenes/GeneratedCommands/StoreSceneResponse"; std::string payload = - get_json_payload_for_identify_trigger_effect_command( + get_json_payload_for_scenes_store_scene_response_command( fields); // Publish our command @@ -112326,11 +118027,11 @@ void uic_mqtt_dotdot_identify_publish_generated_trigger_effect_command( false); } /** - * @brief Publishes an incoming/generated AddGroup command for - * the Groups cluster. + * @brief Publishes an incoming/generated RecallScene command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/AddGroup + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RecallScene * * @param unid The UNID of the node that sent us the command. * @@ -112340,19 +118041,19 @@ void uic_mqtt_dotdot_identify_publish_generated_trigger_effect_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_add_group_command( +void uic_mqtt_dotdot_scenes_publish_generated_recall_scene_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_add_group_fields_t *fields + const uic_mqtt_dotdot_scenes_command_recall_scene_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/AddGroup"; + topic += "Scenes/GeneratedCommands/RecallScene"; std::string payload = - get_json_payload_for_groups_add_group_command( + get_json_payload_for_scenes_recall_scene_command( fields); // Publish our command @@ -112362,11 +118063,11 @@ void uic_mqtt_dotdot_groups_publish_generated_add_group_command( false); } /** - * @brief Publishes an incoming/generated AddGroupResponse command for - * the Groups cluster. + * @brief Publishes an incoming/generated GetSceneMembership command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/AddGroupResponse + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/GetSceneMembership * * @param unid The UNID of the node that sent us the command. * @@ -112376,19 +118077,19 @@ void uic_mqtt_dotdot_groups_publish_generated_add_group_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_add_group_response_command( +void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_add_group_response_fields_t *fields + const uic_mqtt_dotdot_scenes_command_get_scene_membership_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/AddGroupResponse"; + topic += "Scenes/GeneratedCommands/GetSceneMembership"; std::string payload = - get_json_payload_for_groups_add_group_response_command( + get_json_payload_for_scenes_get_scene_membership_command( fields); // Publish our command @@ -112398,11 +118099,11 @@ void uic_mqtt_dotdot_groups_publish_generated_add_group_response_command( false); } /** - * @brief Publishes an incoming/generated ViewGroup command for - * the Groups cluster. + * @brief Publishes an incoming/generated GetSceneMembershipResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/ViewGroup + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/GetSceneMembershipResponse * * @param unid The UNID of the node that sent us the command. * @@ -112412,19 +118113,19 @@ void uic_mqtt_dotdot_groups_publish_generated_add_group_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_view_group_command( +void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_view_group_fields_t *fields + const uic_mqtt_dotdot_scenes_command_get_scene_membership_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/ViewGroup"; + topic += "Scenes/GeneratedCommands/GetSceneMembershipResponse"; std::string payload = - get_json_payload_for_groups_view_group_command( + get_json_payload_for_scenes_get_scene_membership_response_command( fields); // Publish our command @@ -112434,11 +118135,11 @@ void uic_mqtt_dotdot_groups_publish_generated_view_group_command( false); } /** - * @brief Publishes an incoming/generated ViewGroupResponse command for - * the Groups cluster. + * @brief Publishes an incoming/generated EnhancedAddScene command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/ViewGroupResponse + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedAddScene * * @param unid The UNID of the node that sent us the command. * @@ -112448,19 +118149,19 @@ void uic_mqtt_dotdot_groups_publish_generated_view_group_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_view_group_response_command( +void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_view_group_response_fields_t *fields + const uic_mqtt_dotdot_scenes_command_enhanced_add_scene_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/ViewGroupResponse"; + topic += "Scenes/GeneratedCommands/EnhancedAddScene"; std::string payload = - get_json_payload_for_groups_view_group_response_command( + get_json_payload_for_scenes_enhanced_add_scene_command( fields); // Publish our command @@ -112470,11 +118171,11 @@ void uic_mqtt_dotdot_groups_publish_generated_view_group_response_command( false); } /** - * @brief Publishes an incoming/generated GetGroupMembership command for - * the Groups cluster. + * @brief Publishes an incoming/generated EnhancedAddSceneResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/GetGroupMembership + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedAddSceneResponse * * @param unid The UNID of the node that sent us the command. * @@ -112484,19 +118185,19 @@ void uic_mqtt_dotdot_groups_publish_generated_view_group_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_command( +void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_get_group_membership_fields_t *fields + const uic_mqtt_dotdot_scenes_command_enhanced_add_scene_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/GetGroupMembership"; + topic += "Scenes/GeneratedCommands/EnhancedAddSceneResponse"; std::string payload = - get_json_payload_for_groups_get_group_membership_command( + get_json_payload_for_scenes_enhanced_add_scene_response_command( fields); // Publish our command @@ -112506,11 +118207,11 @@ void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_command( false); } /** - * @brief Publishes an incoming/generated GetGroupMembershipResponse command for - * the Groups cluster. + * @brief Publishes an incoming/generated EnhancedViewScene command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/GetGroupMembershipResponse + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedViewScene * * @param unid The UNID of the node that sent us the command. * @@ -112520,19 +118221,19 @@ void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_response_command( +void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_get_group_membership_response_fields_t *fields + const uic_mqtt_dotdot_scenes_command_enhanced_view_scene_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/GetGroupMembershipResponse"; + topic += "Scenes/GeneratedCommands/EnhancedViewScene"; std::string payload = - get_json_payload_for_groups_get_group_membership_response_command( + get_json_payload_for_scenes_enhanced_view_scene_command( fields); // Publish our command @@ -112542,11 +118243,11 @@ void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_response_comm false); } /** - * @brief Publishes an incoming/generated RemoveGroup command for - * the Groups cluster. + * @brief Publishes an incoming/generated EnhancedViewSceneResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/RemoveGroup + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedViewSceneResponse * * @param unid The UNID of the node that sent us the command. * @@ -112556,19 +118257,19 @@ void uic_mqtt_dotdot_groups_publish_generated_get_group_membership_response_comm * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_remove_group_command( +void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_remove_group_fields_t *fields + const uic_mqtt_dotdot_scenes_command_enhanced_view_scene_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/RemoveGroup"; + topic += "Scenes/GeneratedCommands/EnhancedViewSceneResponse"; std::string payload = - get_json_payload_for_groups_remove_group_command( + get_json_payload_for_scenes_enhanced_view_scene_response_command( fields); // Publish our command @@ -112578,11 +118279,11 @@ void uic_mqtt_dotdot_groups_publish_generated_remove_group_command( false); } /** - * @brief Publishes an incoming/generated RemoveGroupResponse command for - * the Groups cluster. + * @brief Publishes an incoming/generated CopyScene command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/RemoveGroupResponse + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/CopyScene * * @param unid The UNID of the node that sent us the command. * @@ -112592,19 +118293,19 @@ void uic_mqtt_dotdot_groups_publish_generated_remove_group_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_groups_publish_generated_remove_group_response_command( +void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_remove_group_response_fields_t *fields + const uic_mqtt_dotdot_scenes_command_copy_scene_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/RemoveGroupResponse"; + topic += "Scenes/GeneratedCommands/CopyScene"; std::string payload = - get_json_payload_for_groups_remove_group_response_command( + get_json_payload_for_scenes_copy_scene_command( fields); // Publish our command @@ -112614,30 +118315,34 @@ void uic_mqtt_dotdot_groups_publish_generated_remove_group_response_command( false); } /** - * @brief Publishes an incoming/generated RemoveAllGroups command for - * the Groups cluster. + * @brief Publishes an incoming/generated CopySceneResponse command for + * the Scenes cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/RemoveAllGroups + * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/CopySceneResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_groups_publish_generated_remove_all_groups_command( +void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_scenes_command_copy_scene_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/RemoveAllGroups"; + topic += "Scenes/GeneratedCommands/CopySceneResponse"; std::string payload = - get_json_payload_for_groups_remove_all_groups_command( - ); + get_json_payload_for_scenes_copy_scene_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112646,34 +118351,30 @@ void uic_mqtt_dotdot_groups_publish_generated_remove_all_groups_command( false); } /** - * @brief Publishes an incoming/generated AddGroupIfIdentifying command for - * the Groups cluster. + * @brief Publishes an incoming/generated Off command for + * the OnOff cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Groups/GeneratedCommands/AddGroupIfIdentifying + * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/Off * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_groups_publish_generated_add_group_if_identifying_command( +void uic_mqtt_dotdot_on_off_publish_generated_off_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_groups_command_add_group_if_identifying_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Groups/GeneratedCommands/AddGroupIfIdentifying"; + topic += "OnOff/GeneratedCommands/Off"; std::string payload = - get_json_payload_for_groups_add_group_if_identifying_command( - fields); + get_json_payload_for_on_off_off_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112682,34 +118383,30 @@ void uic_mqtt_dotdot_groups_publish_generated_add_group_if_identifying_command( false); } /** - * @brief Publishes an incoming/generated AddScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated On command for + * the OnOff cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/AddScene + * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/On * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_scenes_publish_generated_add_scene_command( +void uic_mqtt_dotdot_on_off_publish_generated_on_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_add_scene_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/AddScene"; + topic += "OnOff/GeneratedCommands/On"; std::string payload = - get_json_payload_for_scenes_add_scene_command( - fields); + get_json_payload_for_on_off_on_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112718,34 +118415,30 @@ void uic_mqtt_dotdot_scenes_publish_generated_add_scene_command( false); } /** - * @brief Publishes an incoming/generated AddSceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated Toggle command for + * the OnOff cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/AddSceneResponse + * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/Toggle * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_scenes_publish_generated_add_scene_response_command( +void uic_mqtt_dotdot_on_off_publish_generated_toggle_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_add_scene_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/AddSceneResponse"; + topic += "OnOff/GeneratedCommands/Toggle"; std::string payload = - get_json_payload_for_scenes_add_scene_response_command( - fields); + get_json_payload_for_on_off_toggle_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112754,11 +118447,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_add_scene_response_command( false); } /** - * @brief Publishes an incoming/generated ViewScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated OffWithEffect command for + * the OnOff cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/ViewScene + * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/OffWithEffect * * @param unid The UNID of the node that sent us the command. * @@ -112768,19 +118461,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_add_scene_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_view_scene_command( +void uic_mqtt_dotdot_on_off_publish_generated_off_with_effect_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_view_scene_fields_t *fields + const uic_mqtt_dotdot_on_off_command_off_with_effect_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/ViewScene"; + topic += "OnOff/GeneratedCommands/OffWithEffect"; std::string payload = - get_json_payload_for_scenes_view_scene_command( + get_json_payload_for_on_off_off_with_effect_command( fields); // Publish our command @@ -112790,34 +118483,30 @@ void uic_mqtt_dotdot_scenes_publish_generated_view_scene_command( false); } /** - * @brief Publishes an incoming/generated ViewSceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated OnWithRecallGlobalScene command for + * the OnOff cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/ViewSceneResponse + * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/OnWithRecallGlobalScene * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_scenes_publish_generated_view_scene_response_command( +void uic_mqtt_dotdot_on_off_publish_generated_on_with_recall_global_scene_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_view_scene_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/ViewSceneResponse"; + topic += "OnOff/GeneratedCommands/OnWithRecallGlobalScene"; std::string payload = - get_json_payload_for_scenes_view_scene_response_command( - fields); + get_json_payload_for_on_off_on_with_recall_global_scene_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -112826,11 +118515,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_view_scene_response_command( false); } /** - * @brief Publishes an incoming/generated RemoveScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated OnWithTimedOff command for + * the OnOff cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveScene + * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/OnWithTimedOff * * @param unid The UNID of the node that sent us the command. * @@ -112840,19 +118529,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_view_scene_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_command( +void uic_mqtt_dotdot_on_off_publish_generated_on_with_timed_off_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_remove_scene_fields_t *fields + const uic_mqtt_dotdot_on_off_command_on_with_timed_off_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/RemoveScene"; + topic += "OnOff/GeneratedCommands/OnWithTimedOff"; std::string payload = - get_json_payload_for_scenes_remove_scene_command( + get_json_payload_for_on_off_on_with_timed_off_command( fields); // Publish our command @@ -112862,11 +118551,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_command( false); } /** - * @brief Publishes an incoming/generated RemoveSceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated MoveToLevel command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveSceneResponse + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveToLevel * * @param unid The UNID of the node that sent us the command. * @@ -112876,19 +118565,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_response_command( +void uic_mqtt_dotdot_level_publish_generated_move_to_level_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_remove_scene_response_fields_t *fields + const uic_mqtt_dotdot_level_command_move_to_level_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/RemoveSceneResponse"; + topic += "Level/GeneratedCommands/MoveToLevel"; std::string payload = - get_json_payload_for_scenes_remove_scene_response_command( + get_json_payload_for_level_move_to_level_command( fields); // Publish our command @@ -112898,11 +118587,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_response_command( false); } /** - * @brief Publishes an incoming/generated RemoveAllScenes command for - * the Scenes cluster. + * @brief Publishes an incoming/generated Move command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveAllScenes + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/Move * * @param unid The UNID of the node that sent us the command. * @@ -112912,19 +118601,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_scene_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_command( +void uic_mqtt_dotdot_level_publish_generated_move_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_remove_all_scenes_fields_t *fields + const uic_mqtt_dotdot_level_command_move_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/RemoveAllScenes"; + topic += "Level/GeneratedCommands/Move"; std::string payload = - get_json_payload_for_scenes_remove_all_scenes_command( + get_json_payload_for_level_move_command( fields); // Publish our command @@ -112934,11 +118623,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_command( false); } /** - * @brief Publishes an incoming/generated RemoveAllScenesResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated Step command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RemoveAllScenesResponse + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/Step * * @param unid The UNID of the node that sent us the command. * @@ -112948,19 +118637,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_response_command( +void uic_mqtt_dotdot_level_publish_generated_step_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_remove_all_scenes_response_fields_t *fields + const uic_mqtt_dotdot_level_command_step_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/RemoveAllScenesResponse"; + topic += "Level/GeneratedCommands/Step"; std::string payload = - get_json_payload_for_scenes_remove_all_scenes_response_command( + get_json_payload_for_level_step_command( fields); // Publish our command @@ -112970,11 +118659,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_response_command false); } /** - * @brief Publishes an incoming/generated StoreScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated Stop command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/StoreScene + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/Stop * * @param unid The UNID of the node that sent us the command. * @@ -112984,19 +118673,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_remove_all_scenes_response_command * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_store_scene_command( +void uic_mqtt_dotdot_level_publish_generated_stop_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_store_scene_fields_t *fields + const uic_mqtt_dotdot_level_command_stop_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/StoreScene"; + topic += "Level/GeneratedCommands/Stop"; std::string payload = - get_json_payload_for_scenes_store_scene_command( + get_json_payload_for_level_stop_command( fields); // Publish our command @@ -113006,11 +118695,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_store_scene_command( false); } /** - * @brief Publishes an incoming/generated StoreSceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated MoveToLevelWithOnOff command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/StoreSceneResponse + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveToLevelWithOnOff * * @param unid The UNID of the node that sent us the command. * @@ -113020,19 +118709,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_store_scene_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_store_scene_response_command( +void uic_mqtt_dotdot_level_publish_generated_move_to_level_with_on_off_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_store_scene_response_fields_t *fields + const uic_mqtt_dotdot_level_command_move_to_level_with_on_off_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/StoreSceneResponse"; + topic += "Level/GeneratedCommands/MoveToLevelWithOnOff"; std::string payload = - get_json_payload_for_scenes_store_scene_response_command( + get_json_payload_for_level_move_to_level_with_on_off_command( fields); // Publish our command @@ -113042,11 +118731,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_store_scene_response_command( false); } /** - * @brief Publishes an incoming/generated RecallScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated MoveWithOnOff command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/RecallScene + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveWithOnOff * * @param unid The UNID of the node that sent us the command. * @@ -113056,19 +118745,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_store_scene_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_recall_scene_command( +void uic_mqtt_dotdot_level_publish_generated_move_with_on_off_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_recall_scene_fields_t *fields + const uic_mqtt_dotdot_level_command_move_with_on_off_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/RecallScene"; + topic += "Level/GeneratedCommands/MoveWithOnOff"; std::string payload = - get_json_payload_for_scenes_recall_scene_command( + get_json_payload_for_level_move_with_on_off_command( fields); // Publish our command @@ -113078,11 +118767,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_recall_scene_command( false); } /** - * @brief Publishes an incoming/generated GetSceneMembership command for - * the Scenes cluster. + * @brief Publishes an incoming/generated StepWithOnOff command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/GetSceneMembership + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/StepWithOnOff * * @param unid The UNID of the node that sent us the command. * @@ -113092,19 +118781,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_recall_scene_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_command( +void uic_mqtt_dotdot_level_publish_generated_step_with_on_off_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_get_scene_membership_fields_t *fields + const uic_mqtt_dotdot_level_command_step_with_on_off_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/GetSceneMembership"; + topic += "Level/GeneratedCommands/StepWithOnOff"; std::string payload = - get_json_payload_for_scenes_get_scene_membership_command( + get_json_payload_for_level_step_with_on_off_command( fields); // Publish our command @@ -113114,11 +118803,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_command( false); } /** - * @brief Publishes an incoming/generated GetSceneMembershipResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated StopWithOnOff command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/GetSceneMembershipResponse + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/StopWithOnOff * * @param unid The UNID of the node that sent us the command. * @@ -113128,19 +118817,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_response_command( +void uic_mqtt_dotdot_level_publish_generated_stop_with_on_off_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_get_scene_membership_response_fields_t *fields + const uic_mqtt_dotdot_level_command_stop_with_on_off_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/GetSceneMembershipResponse"; + topic += "Level/GeneratedCommands/StopWithOnOff"; std::string payload = - get_json_payload_for_scenes_get_scene_membership_response_command( + get_json_payload_for_level_stop_with_on_off_command( fields); // Publish our command @@ -113150,11 +118839,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_response_comm false); } /** - * @brief Publishes an incoming/generated EnhancedAddScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated MoveToClosestFrequency command for + * the Level cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedAddScene + * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveToClosestFrequency * * @param unid The UNID of the node that sent us the command. * @@ -113164,19 +118853,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_get_scene_membership_response_comm * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_command( +void uic_mqtt_dotdot_level_publish_generated_move_to_closest_frequency_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_enhanced_add_scene_fields_t *fields + const uic_mqtt_dotdot_level_command_move_to_closest_frequency_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/EnhancedAddScene"; + topic += "Level/GeneratedCommands/MoveToClosestFrequency"; std::string payload = - get_json_payload_for_scenes_enhanced_add_scene_command( + get_json_payload_for_level_move_to_closest_frequency_command( fields); // Publish our command @@ -113186,11 +118875,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_command( false); } /** - * @brief Publishes an incoming/generated EnhancedAddSceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated ResetAlarm command for + * the Alarms cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedAddSceneResponse + * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/ResetAlarm * * @param unid The UNID of the node that sent us the command. * @@ -113200,19 +118889,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_response_command( +void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_enhanced_add_scene_response_fields_t *fields + const uic_mqtt_dotdot_alarms_command_reset_alarm_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/EnhancedAddSceneResponse"; + topic += "Alarms/GeneratedCommands/ResetAlarm"; std::string payload = - get_json_payload_for_scenes_enhanced_add_scene_response_command( + get_json_payload_for_alarms_reset_alarm_command( fields); // Publish our command @@ -113222,11 +118911,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_response_comman false); } /** - * @brief Publishes an incoming/generated EnhancedViewScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated Alarm command for + * the Alarms cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedViewScene + * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/Alarm * * @param unid The UNID of the node that sent us the command. * @@ -113236,19 +118925,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_add_scene_response_comman * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_command( +void uic_mqtt_dotdot_alarms_publish_generated_alarm_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_enhanced_view_scene_fields_t *fields + const uic_mqtt_dotdot_alarms_command_alarm_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/EnhancedViewScene"; + topic += "Alarms/GeneratedCommands/Alarm"; std::string payload = - get_json_payload_for_scenes_enhanced_view_scene_command( + get_json_payload_for_alarms_alarm_command( fields); // Publish our command @@ -113258,34 +118947,30 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_command( false); } /** - * @brief Publishes an incoming/generated EnhancedViewSceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated ResetAllAlarms command for + * the Alarms cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/EnhancedViewSceneResponse + * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/ResetAllAlarms * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_response_command( +void uic_mqtt_dotdot_alarms_publish_generated_reset_all_alarms_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_enhanced_view_scene_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/EnhancedViewSceneResponse"; + topic += "Alarms/GeneratedCommands/ResetAllAlarms"; std::string payload = - get_json_payload_for_scenes_enhanced_view_scene_response_command( - fields); + get_json_payload_for_alarms_reset_all_alarms_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -113294,11 +118979,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_response_comma false); } /** - * @brief Publishes an incoming/generated CopyScene command for - * the Scenes cluster. + * @brief Publishes an incoming/generated GetAlarmResponse command for + * the Alarms cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/CopyScene + * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/GetAlarmResponse * * @param unid The UNID of the node that sent us the command. * @@ -113308,19 +118993,19 @@ void uic_mqtt_dotdot_scenes_publish_generated_enhanced_view_scene_response_comma * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_command( +void uic_mqtt_dotdot_alarms_publish_generated_get_alarm_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_copy_scene_fields_t *fields + const uic_mqtt_dotdot_alarms_command_get_alarm_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/CopyScene"; + topic += "Alarms/GeneratedCommands/GetAlarmResponse"; std::string payload = - get_json_payload_for_scenes_copy_scene_command( + get_json_payload_for_alarms_get_alarm_response_command( fields); // Publish our command @@ -113330,34 +119015,30 @@ void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_command( false); } /** - * @brief Publishes an incoming/generated CopySceneResponse command for - * the Scenes cluster. + * @brief Publishes an incoming/generated GetAlarm command for + * the Alarms cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Scenes/GeneratedCommands/CopySceneResponse + * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/GetAlarm * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_response_command( +void uic_mqtt_dotdot_alarms_publish_generated_get_alarm_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_scenes_command_copy_scene_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Scenes/GeneratedCommands/CopySceneResponse"; + topic += "Alarms/GeneratedCommands/GetAlarm"; std::string payload = - get_json_payload_for_scenes_copy_scene_response_command( - fields); + get_json_payload_for_alarms_get_alarm_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -113366,11 +119047,11 @@ void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_response_command( false); } /** - * @brief Publishes an incoming/generated Off command for - * the OnOff cluster. + * @brief Publishes an incoming/generated ResetAlarmLog command for + * the Alarms cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/Off + * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/ResetAlarmLog * * @param unid The UNID of the node that sent us the command. * @@ -113378,17 +119059,17 @@ void uic_mqtt_dotdot_scenes_publish_generated_copy_scene_response_command( * * */ -void uic_mqtt_dotdot_on_off_publish_generated_off_command( +void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_log_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "OnOff/GeneratedCommands/Off"; + topic += "Alarms/GeneratedCommands/ResetAlarmLog"; std::string payload = - get_json_payload_for_on_off_off_command( + get_json_payload_for_alarms_reset_alarm_log_command( ); // Publish our command @@ -113398,11 +119079,11 @@ void uic_mqtt_dotdot_on_off_publish_generated_off_command( false); } /** - * @brief Publishes an incoming/generated On command for - * the OnOff cluster. + * @brief Publishes an incoming/generated CheckIn command for + * the PollControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/On + * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/CheckIn * * @param unid The UNID of the node that sent us the command. * @@ -113410,17 +119091,17 @@ void uic_mqtt_dotdot_on_off_publish_generated_off_command( * * */ -void uic_mqtt_dotdot_on_off_publish_generated_on_command( +void uic_mqtt_dotdot_poll_control_publish_generated_check_in_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "OnOff/GeneratedCommands/On"; + topic += "PollControl/GeneratedCommands/CheckIn"; std::string payload = - get_json_payload_for_on_off_on_command( + get_json_payload_for_poll_control_check_in_command( ); // Publish our command @@ -113430,30 +119111,34 @@ void uic_mqtt_dotdot_on_off_publish_generated_on_command( false); } /** - * @brief Publishes an incoming/generated Toggle command for - * the OnOff cluster. + * @brief Publishes an incoming/generated CheckInResponse command for + * the PollControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/Toggle + * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/CheckInResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_on_off_publish_generated_toggle_command( +void uic_mqtt_dotdot_poll_control_publish_generated_check_in_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_poll_control_command_check_in_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "OnOff/GeneratedCommands/Toggle"; + topic += "PollControl/GeneratedCommands/CheckInResponse"; std::string payload = - get_json_payload_for_on_off_toggle_command( - ); + get_json_payload_for_poll_control_check_in_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -113462,34 +119147,30 @@ void uic_mqtt_dotdot_on_off_publish_generated_toggle_command( false); } /** - * @brief Publishes an incoming/generated OffWithEffect command for - * the OnOff cluster. + * @brief Publishes an incoming/generated FastPollStop command for + * the PollControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/OffWithEffect + * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/FastPollStop * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_on_off_publish_generated_off_with_effect_command( +void uic_mqtt_dotdot_poll_control_publish_generated_fast_poll_stop_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_on_off_command_off_with_effect_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "OnOff/GeneratedCommands/OffWithEffect"; + topic += "PollControl/GeneratedCommands/FastPollStop"; std::string payload = - get_json_payload_for_on_off_off_with_effect_command( - fields); + get_json_payload_for_poll_control_fast_poll_stop_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -113498,30 +119179,34 @@ void uic_mqtt_dotdot_on_off_publish_generated_off_with_effect_command( false); } /** - * @brief Publishes an incoming/generated OnWithRecallGlobalScene command for - * the OnOff cluster. + * @brief Publishes an incoming/generated SetLongPollInterval command for + * the PollControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/OnWithRecallGlobalScene + * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/SetLongPollInterval * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_on_off_publish_generated_on_with_recall_global_scene_command( +void uic_mqtt_dotdot_poll_control_publish_generated_set_long_poll_interval_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_poll_control_command_set_long_poll_interval_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "OnOff/GeneratedCommands/OnWithRecallGlobalScene"; + topic += "PollControl/GeneratedCommands/SetLongPollInterval"; std::string payload = - get_json_payload_for_on_off_on_with_recall_global_scene_command( - ); + get_json_payload_for_poll_control_set_long_poll_interval_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -113530,11 +119215,11 @@ void uic_mqtt_dotdot_on_off_publish_generated_on_with_recall_global_scene_comman false); } /** - * @brief Publishes an incoming/generated OnWithTimedOff command for - * the OnOff cluster. + * @brief Publishes an incoming/generated SetShortPollInterval command for + * the PollControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/OnOff/GeneratedCommands/OnWithTimedOff + * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/SetShortPollInterval * * @param unid The UNID of the node that sent us the command. * @@ -113544,19 +119229,19 @@ void uic_mqtt_dotdot_on_off_publish_generated_on_with_recall_global_scene_comman * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_on_off_publish_generated_on_with_timed_off_command( +void uic_mqtt_dotdot_poll_control_publish_generated_set_short_poll_interval_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_on_off_command_on_with_timed_off_fields_t *fields + const uic_mqtt_dotdot_poll_control_command_set_short_poll_interval_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "OnOff/GeneratedCommands/OnWithTimedOff"; + topic += "PollControl/GeneratedCommands/SetShortPollInterval"; std::string payload = - get_json_payload_for_on_off_on_with_timed_off_command( + get_json_payload_for_poll_control_set_short_poll_interval_command( fields); // Publish our command @@ -113566,11 +119251,11 @@ void uic_mqtt_dotdot_on_off_publish_generated_on_with_timed_off_command( false); } /** - * @brief Publishes an incoming/generated MoveToLevel command for - * the Level cluster. + * @brief Publishes an incoming/generated LockDoor command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveToLevel + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/LockDoor * * @param unid The UNID of the node that sent us the command. * @@ -113580,19 +119265,19 @@ void uic_mqtt_dotdot_on_off_publish_generated_on_with_timed_off_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_move_to_level_command( +void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_move_to_level_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_lock_door_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/MoveToLevel"; + topic += "DoorLock/GeneratedCommands/LockDoor"; std::string payload = - get_json_payload_for_level_move_to_level_command( + get_json_payload_for_door_lock_lock_door_command( fields); // Publish our command @@ -113602,11 +119287,11 @@ void uic_mqtt_dotdot_level_publish_generated_move_to_level_command( false); } /** - * @brief Publishes an incoming/generated Move command for - * the Level cluster. + * @brief Publishes an incoming/generated LockDoorResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/Move + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/LockDoorResponse * * @param unid The UNID of the node that sent us the command. * @@ -113616,19 +119301,19 @@ void uic_mqtt_dotdot_level_publish_generated_move_to_level_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_move_command( +void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_move_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_lock_door_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/Move"; + topic += "DoorLock/GeneratedCommands/LockDoorResponse"; std::string payload = - get_json_payload_for_level_move_command( + get_json_payload_for_door_lock_lock_door_response_command( fields); // Publish our command @@ -113638,11 +119323,11 @@ void uic_mqtt_dotdot_level_publish_generated_move_command( false); } /** - * @brief Publishes an incoming/generated Step command for - * the Level cluster. + * @brief Publishes an incoming/generated UnlockDoor command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/Step + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockDoor * * @param unid The UNID of the node that sent us the command. * @@ -113652,19 +119337,19 @@ void uic_mqtt_dotdot_level_publish_generated_move_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_step_command( +void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_step_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_unlock_door_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/Step"; + topic += "DoorLock/GeneratedCommands/UnlockDoor"; std::string payload = - get_json_payload_for_level_step_command( + get_json_payload_for_door_lock_unlock_door_command( fields); // Publish our command @@ -113674,11 +119359,11 @@ void uic_mqtt_dotdot_level_publish_generated_step_command( false); } /** - * @brief Publishes an incoming/generated Stop command for - * the Level cluster. + * @brief Publishes an incoming/generated UnlockDoorResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/Stop + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockDoorResponse * * @param unid The UNID of the node that sent us the command. * @@ -113688,19 +119373,19 @@ void uic_mqtt_dotdot_level_publish_generated_step_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_stop_command( +void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_stop_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_unlock_door_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/Stop"; + topic += "DoorLock/GeneratedCommands/UnlockDoorResponse"; std::string payload = - get_json_payload_for_level_stop_command( + get_json_payload_for_door_lock_unlock_door_response_command( fields); // Publish our command @@ -113710,11 +119395,11 @@ void uic_mqtt_dotdot_level_publish_generated_stop_command( false); } /** - * @brief Publishes an incoming/generated MoveToLevelWithOnOff command for - * the Level cluster. + * @brief Publishes an incoming/generated Toggle command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveToLevelWithOnOff + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/Toggle * * @param unid The UNID of the node that sent us the command. * @@ -113724,19 +119409,19 @@ void uic_mqtt_dotdot_level_publish_generated_stop_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_move_to_level_with_on_off_command( +void uic_mqtt_dotdot_door_lock_publish_generated_toggle_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_move_to_level_with_on_off_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_toggle_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/MoveToLevelWithOnOff"; + topic += "DoorLock/GeneratedCommands/Toggle"; std::string payload = - get_json_payload_for_level_move_to_level_with_on_off_command( + get_json_payload_for_door_lock_toggle_command( fields); // Publish our command @@ -113746,11 +119431,11 @@ void uic_mqtt_dotdot_level_publish_generated_move_to_level_with_on_off_command( false); } /** - * @brief Publishes an incoming/generated MoveWithOnOff command for - * the Level cluster. + * @brief Publishes an incoming/generated ToggleResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveWithOnOff + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ToggleResponse * * @param unid The UNID of the node that sent us the command. * @@ -113760,19 +119445,19 @@ void uic_mqtt_dotdot_level_publish_generated_move_to_level_with_on_off_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_move_with_on_off_command( +void uic_mqtt_dotdot_door_lock_publish_generated_toggle_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_move_with_on_off_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_toggle_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/MoveWithOnOff"; + topic += "DoorLock/GeneratedCommands/ToggleResponse"; std::string payload = - get_json_payload_for_level_move_with_on_off_command( + get_json_payload_for_door_lock_toggle_response_command( fields); // Publish our command @@ -113782,11 +119467,11 @@ void uic_mqtt_dotdot_level_publish_generated_move_with_on_off_command( false); } /** - * @brief Publishes an incoming/generated StepWithOnOff command for - * the Level cluster. + * @brief Publishes an incoming/generated UnlockWithTimeout command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/StepWithOnOff + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockWithTimeout * * @param unid The UNID of the node that sent us the command. * @@ -113796,19 +119481,19 @@ void uic_mqtt_dotdot_level_publish_generated_move_with_on_off_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_step_with_on_off_command( +void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_step_with_on_off_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_unlock_with_timeout_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/StepWithOnOff"; + topic += "DoorLock/GeneratedCommands/UnlockWithTimeout"; std::string payload = - get_json_payload_for_level_step_with_on_off_command( + get_json_payload_for_door_lock_unlock_with_timeout_command( fields); // Publish our command @@ -113818,11 +119503,11 @@ void uic_mqtt_dotdot_level_publish_generated_step_with_on_off_command( false); } /** - * @brief Publishes an incoming/generated StopWithOnOff command for - * the Level cluster. + * @brief Publishes an incoming/generated UnlockWithTimeoutResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/StopWithOnOff + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockWithTimeoutResponse * * @param unid The UNID of the node that sent us the command. * @@ -113832,19 +119517,19 @@ void uic_mqtt_dotdot_level_publish_generated_step_with_on_off_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_stop_with_on_off_command( +void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_stop_with_on_off_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_unlock_with_timeout_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/StopWithOnOff"; + topic += "DoorLock/GeneratedCommands/UnlockWithTimeoutResponse"; std::string payload = - get_json_payload_for_level_stop_with_on_off_command( + get_json_payload_for_door_lock_unlock_with_timeout_response_command( fields); // Publish our command @@ -113854,11 +119539,11 @@ void uic_mqtt_dotdot_level_publish_generated_stop_with_on_off_command( false); } /** - * @brief Publishes an incoming/generated MoveToClosestFrequency command for - * the Level cluster. + * @brief Publishes an incoming/generated GetLogRecord command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Level/GeneratedCommands/MoveToClosestFrequency + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetLogRecord * * @param unid The UNID of the node that sent us the command. * @@ -113868,19 +119553,19 @@ void uic_mqtt_dotdot_level_publish_generated_stop_with_on_off_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_level_publish_generated_move_to_closest_frequency_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_level_command_move_to_closest_frequency_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_log_record_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Level/GeneratedCommands/MoveToClosestFrequency"; + topic += "DoorLock/GeneratedCommands/GetLogRecord"; std::string payload = - get_json_payload_for_level_move_to_closest_frequency_command( + get_json_payload_for_door_lock_get_log_record_command( fields); // Publish our command @@ -113890,11 +119575,11 @@ void uic_mqtt_dotdot_level_publish_generated_move_to_closest_frequency_command( false); } /** - * @brief Publishes an incoming/generated ResetAlarm command for - * the Alarms cluster. + * @brief Publishes an incoming/generated GetLogRecordResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/ResetAlarm + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetLogRecordResponse * * @param unid The UNID of the node that sent us the command. * @@ -113904,19 +119589,19 @@ void uic_mqtt_dotdot_level_publish_generated_move_to_closest_frequency_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_alarms_command_reset_alarm_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_log_record_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Alarms/GeneratedCommands/ResetAlarm"; + topic += "DoorLock/GeneratedCommands/GetLogRecordResponse"; std::string payload = - get_json_payload_for_alarms_reset_alarm_command( + get_json_payload_for_door_lock_get_log_record_response_command( fields); // Publish our command @@ -113926,11 +119611,11 @@ void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_command( false); } /** - * @brief Publishes an incoming/generated Alarm command for - * the Alarms cluster. + * @brief Publishes an incoming/generated SetPINCode command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/Alarm + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetPINCode * * @param unid The UNID of the node that sent us the command. * @@ -113940,19 +119625,19 @@ void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_alarms_publish_generated_alarm_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_alarms_command_alarm_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_pin_code_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Alarms/GeneratedCommands/Alarm"; + topic += "DoorLock/GeneratedCommands/SetPINCode"; std::string payload = - get_json_payload_for_alarms_alarm_command( + get_json_payload_for_door_lock_set_pin_code_command( fields); // Publish our command @@ -113962,30 +119647,34 @@ void uic_mqtt_dotdot_alarms_publish_generated_alarm_command( false); } /** - * @brief Publishes an incoming/generated ResetAllAlarms command for - * the Alarms cluster. + * @brief Publishes an incoming/generated SetPINCodeResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/ResetAllAlarms + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetPINCodeResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_alarms_publish_generated_reset_all_alarms_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_door_lock_command_set_pin_code_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Alarms/GeneratedCommands/ResetAllAlarms"; + topic += "DoorLock/GeneratedCommands/SetPINCodeResponse"; std::string payload = - get_json_payload_for_alarms_reset_all_alarms_command( - ); + get_json_payload_for_door_lock_set_pin_code_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -113994,11 +119683,11 @@ void uic_mqtt_dotdot_alarms_publish_generated_reset_all_alarms_command( false); } /** - * @brief Publishes an incoming/generated GetAlarmResponse command for - * the Alarms cluster. + * @brief Publishes an incoming/generated GetPINCode command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/GetAlarmResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetPINCode * * @param unid The UNID of the node that sent us the command. * @@ -114008,19 +119697,19 @@ void uic_mqtt_dotdot_alarms_publish_generated_reset_all_alarms_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_alarms_publish_generated_get_alarm_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_alarms_command_get_alarm_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_pin_code_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Alarms/GeneratedCommands/GetAlarmResponse"; + topic += "DoorLock/GeneratedCommands/GetPINCode"; std::string payload = - get_json_payload_for_alarms_get_alarm_response_command( + get_json_payload_for_door_lock_get_pin_code_command( fields); // Publish our command @@ -114030,30 +119719,34 @@ void uic_mqtt_dotdot_alarms_publish_generated_get_alarm_response_command( false); } /** - * @brief Publishes an incoming/generated GetAlarm command for - * the Alarms cluster. + * @brief Publishes an incoming/generated GetPINCodeResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/GetAlarm + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetPINCodeResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_alarms_publish_generated_get_alarm_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Alarms/GeneratedCommands/GetAlarm"; + topic += "DoorLock/GeneratedCommands/GetPINCodeResponse"; std::string payload = - get_json_payload_for_alarms_get_alarm_command( - ); + get_json_payload_for_door_lock_get_pin_code_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -114062,30 +119755,34 @@ void uic_mqtt_dotdot_alarms_publish_generated_get_alarm_command( false); } /** - * @brief Publishes an incoming/generated ResetAlarmLog command for - * the Alarms cluster. + * @brief Publishes an incoming/generated ClearPINCode command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Alarms/GeneratedCommands/ResetAlarmLog + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearPINCode * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_log_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_door_lock_command_clear_pin_code_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Alarms/GeneratedCommands/ResetAlarmLog"; + topic += "DoorLock/GeneratedCommands/ClearPINCode"; std::string payload = - get_json_payload_for_alarms_reset_alarm_log_command( - ); + get_json_payload_for_door_lock_clear_pin_code_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -114094,30 +119791,34 @@ void uic_mqtt_dotdot_alarms_publish_generated_reset_alarm_log_command( false); } /** - * @brief Publishes an incoming/generated CheckIn command for - * the PollControl cluster. + * @brief Publishes an incoming/generated ClearPINCodeResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/CheckIn + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearPINCodeResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_poll_control_publish_generated_check_in_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_door_lock_command_clear_pin_code_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "PollControl/GeneratedCommands/CheckIn"; + topic += "DoorLock/GeneratedCommands/ClearPINCodeResponse"; std::string payload = - get_json_payload_for_poll_control_check_in_command( - ); + get_json_payload_for_door_lock_clear_pin_code_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -114126,34 +119827,30 @@ void uic_mqtt_dotdot_poll_control_publish_generated_check_in_command( false); } /** - * @brief Publishes an incoming/generated CheckInResponse command for - * the PollControl cluster. + * @brief Publishes an incoming/generated ClearAllPINCodes command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/CheckInResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllPINCodes * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_poll_control_publish_generated_check_in_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_poll_control_command_check_in_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "PollControl/GeneratedCommands/CheckInResponse"; + topic += "DoorLock/GeneratedCommands/ClearAllPINCodes"; std::string payload = - get_json_payload_for_poll_control_check_in_response_command( - fields); + get_json_payload_for_door_lock_clear_all_pin_codes_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -114162,30 +119859,34 @@ void uic_mqtt_dotdot_poll_control_publish_generated_check_in_response_command( false); } /** - * @brief Publishes an incoming/generated FastPollStop command for - * the PollControl cluster. + * @brief Publishes an incoming/generated ClearAllPINCodesResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/FastPollStop + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllPINCodesResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_poll_control_publish_generated_fast_poll_stop_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_door_lock_command_clear_all_pin_codes_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "PollControl/GeneratedCommands/FastPollStop"; + topic += "DoorLock/GeneratedCommands/ClearAllPINCodesResponse"; std::string payload = - get_json_payload_for_poll_control_fast_poll_stop_command( - ); + get_json_payload_for_door_lock_clear_all_pin_codes_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -114194,11 +119895,11 @@ void uic_mqtt_dotdot_poll_control_publish_generated_fast_poll_stop_command( false); } /** - * @brief Publishes an incoming/generated SetLongPollInterval command for - * the PollControl cluster. + * @brief Publishes an incoming/generated SetUserStatus command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/SetLongPollInterval + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserStatus * * @param unid The UNID of the node that sent us the command. * @@ -114208,19 +119909,19 @@ void uic_mqtt_dotdot_poll_control_publish_generated_fast_poll_stop_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_poll_control_publish_generated_set_long_poll_interval_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_poll_control_command_set_long_poll_interval_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_user_status_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "PollControl/GeneratedCommands/SetLongPollInterval"; + topic += "DoorLock/GeneratedCommands/SetUserStatus"; std::string payload = - get_json_payload_for_poll_control_set_long_poll_interval_command( + get_json_payload_for_door_lock_set_user_status_command( fields); // Publish our command @@ -114230,11 +119931,11 @@ void uic_mqtt_dotdot_poll_control_publish_generated_set_long_poll_interval_comma false); } /** - * @brief Publishes an incoming/generated SetShortPollInterval command for - * the PollControl cluster. + * @brief Publishes an incoming/generated SetUserStatusResponse command for + * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/PollControl/GeneratedCommands/SetShortPollInterval + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserStatusResponse * * @param unid The UNID of the node that sent us the command. * @@ -114244,19 +119945,19 @@ void uic_mqtt_dotdot_poll_control_publish_generated_set_long_poll_interval_comma * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_poll_control_publish_generated_set_short_poll_interval_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_poll_control_command_set_short_poll_interval_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_user_status_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "PollControl/GeneratedCommands/SetShortPollInterval"; + topic += "DoorLock/GeneratedCommands/SetUserStatusResponse"; std::string payload = - get_json_payload_for_poll_control_set_short_poll_interval_command( + get_json_payload_for_door_lock_set_user_status_response_command( fields); // Publish our command @@ -114266,11 +119967,11 @@ void uic_mqtt_dotdot_poll_control_publish_generated_set_short_poll_interval_comm false); } /** - * @brief Publishes an incoming/generated LockDoor command for + * @brief Publishes an incoming/generated GetUserStatus command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/LockDoor + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserStatus * * @param unid The UNID of the node that sent us the command. * @@ -114280,19 +119981,19 @@ void uic_mqtt_dotdot_poll_control_publish_generated_set_short_poll_interval_comm * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_lock_door_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_user_status_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/LockDoor"; + topic += "DoorLock/GeneratedCommands/GetUserStatus"; std::string payload = - get_json_payload_for_door_lock_lock_door_command( + get_json_payload_for_door_lock_get_user_status_command( fields); // Publish our command @@ -114302,11 +120003,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_command( false); } /** - * @brief Publishes an incoming/generated LockDoorResponse command for + * @brief Publishes an incoming/generated GetUserStatusResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/LockDoorResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserStatusResponse * * @param unid The UNID of the node that sent us the command. * @@ -114316,19 +120017,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_lock_door_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_user_status_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/LockDoorResponse"; + topic += "DoorLock/GeneratedCommands/GetUserStatusResponse"; std::string payload = - get_json_payload_for_door_lock_lock_door_response_command( + get_json_payload_for_door_lock_get_user_status_response_command( fields); // Publish our command @@ -114338,11 +120039,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_response_command( false); } /** - * @brief Publishes an incoming/generated UnlockDoor command for + * @brief Publishes an incoming/generated SetWeekdaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockDoor + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetWeekdaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114352,19 +120053,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_lock_door_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_unlock_door_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_weekday_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/UnlockDoor"; + topic += "DoorLock/GeneratedCommands/SetWeekdaySchedule"; std::string payload = - get_json_payload_for_door_lock_unlock_door_command( + get_json_payload_for_door_lock_set_weekday_schedule_command( fields); // Publish our command @@ -114374,11 +120075,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_command( false); } /** - * @brief Publishes an incoming/generated UnlockDoorResponse command for + * @brief Publishes an incoming/generated SetWeekdayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockDoorResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetWeekdayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114388,19 +120089,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_unlock_door_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_weekday_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/UnlockDoorResponse"; + topic += "DoorLock/GeneratedCommands/SetWeekdayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_unlock_door_response_command( + get_json_payload_for_door_lock_set_weekday_schedule_response_command( fields); // Publish our command @@ -114410,11 +120111,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_response_command( false); } /** - * @brief Publishes an incoming/generated Toggle command for + * @brief Publishes an incoming/generated GetWeekdaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/Toggle + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetWeekdaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114424,19 +120125,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_door_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_toggle_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_toggle_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_weekday_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/Toggle"; + topic += "DoorLock/GeneratedCommands/GetWeekdaySchedule"; std::string payload = - get_json_payload_for_door_lock_toggle_command( + get_json_payload_for_door_lock_get_weekday_schedule_command( fields); // Publish our command @@ -114446,11 +120147,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_toggle_command( false); } /** - * @brief Publishes an incoming/generated ToggleResponse command for + * @brief Publishes an incoming/generated GetWeekdayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ToggleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetWeekdayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114460,19 +120161,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_toggle_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_toggle_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_toggle_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_weekday_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ToggleResponse"; + topic += "DoorLock/GeneratedCommands/GetWeekdayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_toggle_response_command( + get_json_payload_for_door_lock_get_weekday_schedule_response_command( fields); // Publish our command @@ -114482,11 +120183,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_toggle_response_command( false); } /** - * @brief Publishes an incoming/generated UnlockWithTimeout command for + * @brief Publishes an incoming/generated ClearWeekdaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockWithTimeout + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearWeekdaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114496,19 +120197,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_toggle_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_unlock_with_timeout_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_weekday_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/UnlockWithTimeout"; + topic += "DoorLock/GeneratedCommands/ClearWeekdaySchedule"; std::string payload = - get_json_payload_for_door_lock_unlock_with_timeout_command( + get_json_payload_for_door_lock_clear_weekday_schedule_command( fields); // Publish our command @@ -114518,11 +120219,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_command( false); } /** - * @brief Publishes an incoming/generated UnlockWithTimeoutResponse command for + * @brief Publishes an incoming/generated ClearWeekdayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnlockWithTimeoutResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearWeekdayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114532,19 +120233,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_unlock_with_timeout_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_weekday_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/UnlockWithTimeoutResponse"; + topic += "DoorLock/GeneratedCommands/ClearWeekdayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_unlock_with_timeout_response_command( + get_json_payload_for_door_lock_clear_weekday_schedule_response_command( fields); // Publish our command @@ -114554,11 +120255,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_response_co false); } /** - * @brief Publishes an incoming/generated GetLogRecord command for + * @brief Publishes an incoming/generated SetYearDaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetLogRecord + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetYearDaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114568,19 +120269,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unlock_with_timeout_response_co * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_log_record_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_year_day_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetLogRecord"; + topic += "DoorLock/GeneratedCommands/SetYearDaySchedule"; std::string payload = - get_json_payload_for_door_lock_get_log_record_command( + get_json_payload_for_door_lock_set_year_day_schedule_command( fields); // Publish our command @@ -114590,11 +120291,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_command( false); } /** - * @brief Publishes an incoming/generated GetLogRecordResponse command for + * @brief Publishes an incoming/generated SetYearDayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetLogRecordResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetYearDayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114604,19 +120305,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_log_record_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_year_day_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetLogRecordResponse"; + topic += "DoorLock/GeneratedCommands/SetYearDayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_get_log_record_response_command( + get_json_payload_for_door_lock_set_year_day_schedule_response_command( fields); // Publish our command @@ -114626,11 +120327,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_response_command false); } /** - * @brief Publishes an incoming/generated SetPINCode command for + * @brief Publishes an incoming/generated GetYearDaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetPINCode + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetYearDaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114640,19 +120341,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_log_record_response_command * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_pin_code_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_year_day_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetPINCode"; + topic += "DoorLock/GeneratedCommands/GetYearDaySchedule"; std::string payload = - get_json_payload_for_door_lock_set_pin_code_command( + get_json_payload_for_door_lock_get_year_day_schedule_command( fields); // Publish our command @@ -114662,11 +120363,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_command( false); } /** - * @brief Publishes an incoming/generated SetPINCodeResponse command for + * @brief Publishes an incoming/generated GetYearDayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetPINCodeResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetYearDayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114676,19 +120377,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_pin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_year_day_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetPINCodeResponse"; + topic += "DoorLock/GeneratedCommands/GetYearDayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_set_pin_code_response_command( + get_json_payload_for_door_lock_get_year_day_schedule_response_command( fields); // Publish our command @@ -114698,11 +120399,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_response_command( false); } /** - * @brief Publishes an incoming/generated GetPINCode command for + * @brief Publishes an incoming/generated ClearYearDaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetPINCode + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearYearDaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114712,19 +120413,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_pin_code_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_pin_code_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_year_day_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetPINCode"; + topic += "DoorLock/GeneratedCommands/ClearYearDaySchedule"; std::string payload = - get_json_payload_for_door_lock_get_pin_code_command( + get_json_payload_for_door_lock_clear_year_day_schedule_command( fields); // Publish our command @@ -114734,11 +120435,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_command( false); } /** - * @brief Publishes an incoming/generated GetPINCodeResponse command for + * @brief Publishes an incoming/generated ClearYearDayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetPINCodeResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearYearDayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114748,19 +120449,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_pin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_year_day_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetPINCodeResponse"; + topic += "DoorLock/GeneratedCommands/ClearYearDayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_get_pin_code_response_command( + get_json_payload_for_door_lock_clear_year_day_schedule_response_command( fields); // Publish our command @@ -114770,11 +120471,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( false); } /** - * @brief Publishes an incoming/generated ClearPINCode command for + * @brief Publishes an incoming/generated SetHolidaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearPINCode + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetHolidaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114784,19 +120485,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_pin_code_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_pin_code_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_holiday_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearPINCode"; + topic += "DoorLock/GeneratedCommands/SetHolidaySchedule"; std::string payload = - get_json_payload_for_door_lock_clear_pin_code_command( + get_json_payload_for_door_lock_set_holiday_schedule_command( fields); // Publish our command @@ -114806,11 +120507,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_command( false); } /** - * @brief Publishes an incoming/generated ClearPINCodeResponse command for + * @brief Publishes an incoming/generated SetHolidayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearPINCodeResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetHolidayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114820,19 +120521,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_pin_code_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_holiday_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearPINCodeResponse"; + topic += "DoorLock/GeneratedCommands/SetHolidayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_clear_pin_code_response_command( + get_json_payload_for_door_lock_set_holiday_schedule_response_command( fields); // Publish our command @@ -114842,30 +120543,34 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_pin_code_response_command false); } /** - * @brief Publishes an incoming/generated ClearAllPINCodes command for + * @brief Publishes an incoming/generated GetHolidaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllPINCodes + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetHolidaySchedule * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_door_lock_command_get_holiday_schedule_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearAllPINCodes"; + topic += "DoorLock/GeneratedCommands/GetHolidaySchedule"; std::string payload = - get_json_payload_for_door_lock_clear_all_pin_codes_command( - ); + get_json_payload_for_door_lock_get_holiday_schedule_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -114874,11 +120579,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_command( false); } /** - * @brief Publishes an incoming/generated ClearAllPINCodesResponse command for + * @brief Publishes an incoming/generated GetHolidayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllPINCodesResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetHolidayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114888,19 +120593,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_all_pin_codes_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_holiday_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearAllPINCodesResponse"; + topic += "DoorLock/GeneratedCommands/GetHolidayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_clear_all_pin_codes_response_command( + get_json_payload_for_door_lock_get_holiday_schedule_response_command( fields); // Publish our command @@ -114910,11 +120615,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_response_co false); } /** - * @brief Publishes an incoming/generated SetUserStatus command for + * @brief Publishes an incoming/generated ClearHolidaySchedule command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserStatus + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearHolidaySchedule * * @param unid The UNID of the node that sent us the command. * @@ -114924,19 +120629,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_pin_codes_response_co * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_user_status_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_holiday_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetUserStatus"; + topic += "DoorLock/GeneratedCommands/ClearHolidaySchedule"; std::string payload = - get_json_payload_for_door_lock_set_user_status_command( + get_json_payload_for_door_lock_clear_holiday_schedule_command( fields); // Publish our command @@ -114946,11 +120651,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_command( false); } /** - * @brief Publishes an incoming/generated SetUserStatusResponse command for + * @brief Publishes an incoming/generated ClearHolidayScheduleResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserStatusResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearHolidayScheduleResponse * * @param unid The UNID of the node that sent us the command. * @@ -114960,19 +120665,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_user_status_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_holiday_schedule_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetUserStatusResponse"; + topic += "DoorLock/GeneratedCommands/ClearHolidayScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_set_user_status_response_command( + get_json_payload_for_door_lock_clear_holiday_schedule_response_command( fields); // Publish our command @@ -114982,11 +120687,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_response_comman false); } /** - * @brief Publishes an incoming/generated GetUserStatus command for + * @brief Publishes an incoming/generated SetUserType command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserStatus + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserType * * @param unid The UNID of the node that sent us the command. * @@ -114996,19 +120701,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_status_response_comman * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_user_status_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_user_type_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetUserStatus"; + topic += "DoorLock/GeneratedCommands/SetUserType"; std::string payload = - get_json_payload_for_door_lock_get_user_status_command( + get_json_payload_for_door_lock_set_user_type_command( fields); // Publish our command @@ -115018,11 +120723,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_command( false); } /** - * @brief Publishes an incoming/generated GetUserStatusResponse command for + * @brief Publishes an incoming/generated SetUserTypeResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserStatusResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserTypeResponse * * @param unid The UNID of the node that sent us the command. * @@ -115032,19 +120737,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_user_status_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_user_type_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetUserStatusResponse"; + topic += "DoorLock/GeneratedCommands/SetUserTypeResponse"; std::string payload = - get_json_payload_for_door_lock_get_user_status_response_command( + get_json_payload_for_door_lock_set_user_type_response_command( fields); // Publish our command @@ -115054,11 +120759,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_response_comman false); } /** - * @brief Publishes an incoming/generated SetWeekdaySchedule command for + * @brief Publishes an incoming/generated GetUserType command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetWeekdaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserType * * @param unid The UNID of the node that sent us the command. * @@ -115068,19 +120773,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_status_response_comman * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_weekday_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_user_type_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetWeekdaySchedule"; + topic += "DoorLock/GeneratedCommands/GetUserType"; std::string payload = - get_json_payload_for_door_lock_set_weekday_schedule_command( + get_json_payload_for_door_lock_get_user_type_command( fields); // Publish our command @@ -115090,11 +120795,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_command( false); } /** - * @brief Publishes an incoming/generated SetWeekdayScheduleResponse command for + * @brief Publishes an incoming/generated GetUserTypeResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetWeekdayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserTypeResponse * * @param unid The UNID of the node that sent us the command. * @@ -115104,19 +120809,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_weekday_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_user_type_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetWeekdayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/GetUserTypeResponse"; std::string payload = - get_json_payload_for_door_lock_set_weekday_schedule_response_command( + get_json_payload_for_door_lock_get_user_type_response_command( fields); // Publish our command @@ -115126,11 +120831,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_response_c false); } /** - * @brief Publishes an incoming/generated GetWeekdaySchedule command for + * @brief Publishes an incoming/generated SetRFIDCode command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetWeekdaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetRFIDCode * * @param unid The UNID of the node that sent us the command. * @@ -115140,19 +120845,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_weekday_schedule_response_c * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_rfid_code_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_weekday_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_rfid_code_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetWeekdaySchedule"; + topic += "DoorLock/GeneratedCommands/SetRFIDCode"; std::string payload = - get_json_payload_for_door_lock_get_weekday_schedule_command( + get_json_payload_for_door_lock_set_rfid_code_command( fields); // Publish our command @@ -115162,11 +120867,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_command( false); } /** - * @brief Publishes an incoming/generated GetWeekdayScheduleResponse command for + * @brief Publishes an incoming/generated SetRFIDCodeResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetWeekdayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetRFIDCodeResponse * * @param unid The UNID of the node that sent us the command. * @@ -115176,19 +120881,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_rfid_code_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_weekday_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_rfid_code_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetWeekdayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/SetRFIDCodeResponse"; std::string payload = - get_json_payload_for_door_lock_get_weekday_schedule_response_command( + get_json_payload_for_door_lock_set_rfid_code_response_command( fields); // Publish our command @@ -115198,11 +120903,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_response_c false); } /** - * @brief Publishes an incoming/generated ClearWeekdaySchedule command for + * @brief Publishes an incoming/generated GetRFIDCode command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearWeekdaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetRFIDCode * * @param unid The UNID of the node that sent us the command. * @@ -115212,19 +120917,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_weekday_schedule_response_c * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_weekday_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_rfid_code_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearWeekdaySchedule"; + topic += "DoorLock/GeneratedCommands/GetRFIDCode"; std::string payload = - get_json_payload_for_door_lock_clear_weekday_schedule_command( + get_json_payload_for_door_lock_get_rfid_code_command( fields); // Publish our command @@ -115234,11 +120939,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_command( false); } /** - * @brief Publishes an incoming/generated ClearWeekdayScheduleResponse command for + * @brief Publishes an incoming/generated GetRFIDCodeResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearWeekdayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetRFIDCodeResponse * * @param unid The UNID of the node that sent us the command. * @@ -115248,19 +120953,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_weekday_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_rfid_code_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearWeekdayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/GetRFIDCodeResponse"; std::string payload = - get_json_payload_for_door_lock_clear_weekday_schedule_response_command( + get_json_payload_for_door_lock_get_rfid_code_response_command( fields); // Publish our command @@ -115270,11 +120975,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_response false); } /** - * @brief Publishes an incoming/generated SetYearDaySchedule command for + * @brief Publishes an incoming/generated ClearRFIDCode command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetYearDaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearRFIDCode * * @param unid The UNID of the node that sent us the command. * @@ -115284,19 +120989,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_weekday_schedule_response * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_year_day_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_rfid_code_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetYearDaySchedule"; + topic += "DoorLock/GeneratedCommands/ClearRFIDCode"; std::string payload = - get_json_payload_for_door_lock_set_year_day_schedule_command( + get_json_payload_for_door_lock_clear_rfid_code_command( fields); // Publish our command @@ -115306,11 +121011,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_command( false); } /** - * @brief Publishes an incoming/generated SetYearDayScheduleResponse command for + * @brief Publishes an incoming/generated ClearRFIDCodeResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetYearDayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearRFIDCodeResponse * * @param unid The UNID of the node that sent us the command. * @@ -115320,19 +121025,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_year_day_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_rfid_code_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetYearDayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/ClearRFIDCodeResponse"; std::string payload = - get_json_payload_for_door_lock_set_year_day_schedule_response_command( + get_json_payload_for_door_lock_clear_rfid_code_response_command( fields); // Publish our command @@ -115342,34 +121047,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_year_day_schedule_response_ false); } /** - * @brief Publishes an incoming/generated GetYearDaySchedule command for + * @brief Publishes an incoming/generated ClearAllRFIDCodes command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetYearDaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllRFIDCodes * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_year_day_schedule_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetYearDaySchedule"; + topic += "DoorLock/GeneratedCommands/ClearAllRFIDCodes"; std::string payload = - get_json_payload_for_door_lock_get_year_day_schedule_command( - fields); + get_json_payload_for_door_lock_clear_all_rfid_codes_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115378,11 +121079,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_command( false); } /** - * @brief Publishes an incoming/generated GetYearDayScheduleResponse command for + * @brief Publishes an incoming/generated ClearAllRFIDCodesResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetYearDayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllRFIDCodesResponse * * @param unid The UNID of the node that sent us the command. * @@ -115392,19 +121093,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_year_day_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_all_rfid_codes_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetYearDayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/ClearAllRFIDCodesResponse"; std::string payload = - get_json_payload_for_door_lock_get_year_day_schedule_response_command( + get_json_payload_for_door_lock_clear_all_rfid_codes_response_command( fields); // Publish our command @@ -115414,11 +121115,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_response_ false); } /** - * @brief Publishes an incoming/generated ClearYearDaySchedule command for + * @brief Publishes an incoming/generated SetUser command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearYearDaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUser * * @param unid The UNID of the node that sent us the command. * @@ -115428,19 +121129,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_year_day_schedule_response_ * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_user_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_year_day_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_user_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearYearDaySchedule"; + topic += "DoorLock/GeneratedCommands/SetUser"; std::string payload = - get_json_payload_for_door_lock_clear_year_day_schedule_command( + get_json_payload_for_door_lock_set_user_command( fields); // Publish our command @@ -115450,11 +121151,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_command false); } /** - * @brief Publishes an incoming/generated ClearYearDayScheduleResponse command for + * @brief Publishes an incoming/generated GetUser command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearYearDayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUser * * @param unid The UNID of the node that sent us the command. * @@ -115464,19 +121165,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_command * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_user_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_year_day_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_user_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearYearDayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/GetUser"; std::string payload = - get_json_payload_for_door_lock_clear_year_day_schedule_response_command( + get_json_payload_for_door_lock_get_user_command( fields); // Publish our command @@ -115486,34 +121187,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_year_day_schedule_respons false); } /** - * @brief Publishes an incoming/generated SetHolidaySchedule command for + * @brief Publishes an incoming/generated GetUserResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetHolidaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_user_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_holiday_schedule_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetHolidaySchedule"; + topic += "DoorLock/GeneratedCommands/GetUserResponse"; std::string payload = - get_json_payload_for_door_lock_set_holiday_schedule_command( - fields); + get_json_payload_for_door_lock_get_user_response_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115522,11 +121219,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_command( false); } /** - * @brief Publishes an incoming/generated SetHolidayScheduleResponse command for + * @brief Publishes an incoming/generated ClearUser command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetHolidayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearUser * * @param unid The UNID of the node that sent us the command. * @@ -115536,19 +121233,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_user_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_holiday_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_user_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetHolidayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/ClearUser"; std::string payload = - get_json_payload_for_door_lock_set_holiday_schedule_response_command( + get_json_payload_for_door_lock_clear_user_command( fields); // Publish our command @@ -115558,11 +121255,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_response_c false); } /** - * @brief Publishes an incoming/generated GetHolidaySchedule command for + * @brief Publishes an incoming/generated OperatingEventNotification command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetHolidaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/OperatingEventNotification * * @param unid The UNID of the node that sent us the command. * @@ -115572,19 +121269,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_holiday_schedule_response_c * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_operating_event_notification_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_holiday_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_operating_event_notification_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetHolidaySchedule"; + topic += "DoorLock/GeneratedCommands/OperatingEventNotification"; std::string payload = - get_json_payload_for_door_lock_get_holiday_schedule_command( + get_json_payload_for_door_lock_operating_event_notification_command( fields); // Publish our command @@ -115594,11 +121291,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_command( false); } /** - * @brief Publishes an incoming/generated GetHolidayScheduleResponse command for + * @brief Publishes an incoming/generated ProgrammingEventNotification command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetHolidayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ProgrammingEventNotification * * @param unid The UNID of the node that sent us the command. * @@ -115608,19 +121305,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_programming_event_notification_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_holiday_schedule_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_programming_event_notification_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetHolidayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/ProgrammingEventNotification"; std::string payload = - get_json_payload_for_door_lock_get_holiday_schedule_response_command( + get_json_payload_for_door_lock_programming_event_notification_command( fields); // Publish our command @@ -115630,11 +121327,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_response_c false); } /** - * @brief Publishes an incoming/generated ClearHolidaySchedule command for + * @brief Publishes an incoming/generated SetCredential command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearHolidaySchedule + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetCredential * * @param unid The UNID of the node that sent us the command. * @@ -115644,19 +121341,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_holiday_schedule_response_c * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_holiday_schedule_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_set_credential_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearHolidaySchedule"; + topic += "DoorLock/GeneratedCommands/SetCredential"; std::string payload = - get_json_payload_for_door_lock_clear_holiday_schedule_command( + get_json_payload_for_door_lock_set_credential_command( fields); // Publish our command @@ -115666,34 +121363,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_command( false); } /** - * @brief Publishes an incoming/generated ClearHolidayScheduleResponse command for + * @brief Publishes an incoming/generated SetCredentialResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearHolidayScheduleResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetCredentialResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_holiday_schedule_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearHolidayScheduleResponse"; + topic += "DoorLock/GeneratedCommands/SetCredentialResponse"; std::string payload = - get_json_payload_for_door_lock_clear_holiday_schedule_response_command( - fields); + get_json_payload_for_door_lock_set_credential_response_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115702,11 +121395,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_response false); } /** - * @brief Publishes an incoming/generated SetUserType command for + * @brief Publishes an incoming/generated GetCredentialStatus command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserType + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetCredentialStatus * * @param unid The UNID of the node that sent us the command. * @@ -115716,19 +121409,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_holiday_schedule_response * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_user_type_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_get_credential_status_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetUserType"; + topic += "DoorLock/GeneratedCommands/GetCredentialStatus"; std::string payload = - get_json_payload_for_door_lock_set_user_type_command( + get_json_payload_for_door_lock_get_credential_status_command( fields); // Publish our command @@ -115738,34 +121431,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_command( false); } /** - * @brief Publishes an incoming/generated SetUserTypeResponse command for + * @brief Publishes an incoming/generated GetCredentialStatusResponse command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUserTypeResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetCredentialStatusResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_user_type_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetUserTypeResponse"; + topic += "DoorLock/GeneratedCommands/GetCredentialStatusResponse"; - std::string payload = - get_json_payload_for_door_lock_set_user_type_response_command( - fields); + std::string payload = + get_json_payload_for_door_lock_get_credential_status_response_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115774,11 +121463,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_response_command( false); } /** - * @brief Publishes an incoming/generated GetUserType command for + * @brief Publishes an incoming/generated ClearCredential command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserType + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearCredential * * @param unid The UNID of the node that sent us the command. * @@ -115788,19 +121477,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_type_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_command( +void uic_mqtt_dotdot_door_lock_publish_generated_clear_credential_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_user_type_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_clear_credential_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetUserType"; + topic += "DoorLock/GeneratedCommands/ClearCredential"; std::string payload = - get_json_payload_for_door_lock_get_user_type_command( + get_json_payload_for_door_lock_clear_credential_command( fields); // Publish our command @@ -115810,11 +121499,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_command( false); } /** - * @brief Publishes an incoming/generated GetUserTypeResponse command for + * @brief Publishes an incoming/generated UnboltDoor command for * the DoorLock cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserTypeResponse + * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnboltDoor * * @param unid The UNID of the node that sent us the command. * @@ -115824,19 +121513,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_response_command( +void uic_mqtt_dotdot_door_lock_publish_generated_unbolt_door_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_user_type_response_fields_t *fields + const uic_mqtt_dotdot_door_lock_command_unbolt_door_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetUserTypeResponse"; + topic += "DoorLock/GeneratedCommands/UnboltDoor"; std::string payload = - get_json_payload_for_door_lock_get_user_type_response_command( + get_json_payload_for_door_lock_unbolt_door_command( fields); // Publish our command @@ -115846,34 +121535,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_type_response_command( false); } /** - * @brief Publishes an incoming/generated SetRFIDCode command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated UpOrOpen command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetRFIDCode + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/UpOrOpen * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_rfid_code_command( +void uic_mqtt_dotdot_window_covering_publish_generated_up_or_open_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_rfid_code_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetRFIDCode"; + topic += "WindowCovering/GeneratedCommands/UpOrOpen"; std::string payload = - get_json_payload_for_door_lock_set_rfid_code_command( - fields); + get_json_payload_for_window_covering_up_or_open_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115882,34 +121567,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_rfid_code_command( false); } /** - * @brief Publishes an incoming/generated SetRFIDCodeResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated DownOrClose command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetRFIDCodeResponse + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/DownOrClose * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_rfid_code_response_command( +void uic_mqtt_dotdot_window_covering_publish_generated_down_or_close_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_rfid_code_response_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetRFIDCodeResponse"; + topic += "WindowCovering/GeneratedCommands/DownOrClose"; std::string payload = - get_json_payload_for_door_lock_set_rfid_code_response_command( - fields); + get_json_payload_for_window_covering_down_or_close_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115918,34 +121599,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_rfid_code_response_command( false); } /** - * @brief Publishes an incoming/generated GetRFIDCode command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated Stop command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetRFIDCode + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/Stop * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_command( +void uic_mqtt_dotdot_window_covering_publish_generated_stop_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_rfid_code_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetRFIDCode"; + topic += "WindowCovering/GeneratedCommands/Stop"; std::string payload = - get_json_payload_for_door_lock_get_rfid_code_command( - fields); + get_json_payload_for_window_covering_stop_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -115954,11 +121631,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_command( false); } /** - * @brief Publishes an incoming/generated GetRFIDCodeResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GoToLiftValue command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetRFIDCodeResponse + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToLiftValue * * @param unid The UNID of the node that sent us the command. * @@ -115968,19 +121645,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_response_command( +void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_value_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_rfid_code_response_fields_t *fields + const uic_mqtt_dotdot_window_covering_command_go_to_lift_value_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetRFIDCodeResponse"; + topic += "WindowCovering/GeneratedCommands/GoToLiftValue"; std::string payload = - get_json_payload_for_door_lock_get_rfid_code_response_command( + get_json_payload_for_window_covering_go_to_lift_value_command( fields); // Publish our command @@ -115990,11 +121667,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_response_command( false); } /** - * @brief Publishes an incoming/generated ClearRFIDCode command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GoToLiftPercentage command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearRFIDCode + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToLiftPercentage * * @param unid The UNID of the node that sent us the command. * @@ -116004,19 +121681,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_rfid_code_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_command( +void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_percentage_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_rfid_code_fields_t *fields + const uic_mqtt_dotdot_window_covering_command_go_to_lift_percentage_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearRFIDCode"; + topic += "WindowCovering/GeneratedCommands/GoToLiftPercentage"; std::string payload = - get_json_payload_for_door_lock_clear_rfid_code_command( + get_json_payload_for_window_covering_go_to_lift_percentage_command( fields); // Publish our command @@ -116026,11 +121703,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_command( false); } /** - * @brief Publishes an incoming/generated ClearRFIDCodeResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GoToTiltValue command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearRFIDCodeResponse + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToTiltValue * * @param unid The UNID of the node that sent us the command. * @@ -116040,19 +121717,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_response_command( +void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_value_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_rfid_code_response_fields_t *fields + const uic_mqtt_dotdot_window_covering_command_go_to_tilt_value_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearRFIDCodeResponse"; + topic += "WindowCovering/GeneratedCommands/GoToTiltValue"; std::string payload = - get_json_payload_for_door_lock_clear_rfid_code_response_command( + get_json_payload_for_window_covering_go_to_tilt_value_command( fields); // Publish our command @@ -116062,30 +121739,34 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_rfid_code_response_comman false); } /** - * @brief Publishes an incoming/generated ClearAllRFIDCodes command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GoToTiltPercentage command for + * the WindowCovering cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllRFIDCodes + * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToTiltPercentage * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_command( +void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_percentage_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_window_covering_command_go_to_tilt_percentage_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearAllRFIDCodes"; + topic += "WindowCovering/GeneratedCommands/GoToTiltPercentage"; std::string payload = - get_json_payload_for_door_lock_clear_all_rfid_codes_command( - ); + get_json_payload_for_window_covering_go_to_tilt_percentage_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116094,11 +121775,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_command( false); } /** - * @brief Publishes an incoming/generated ClearAllRFIDCodesResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GoToPercent command for + * the BarrierControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearAllRFIDCodesResponse + * ucl/by-unid/UNID/epID/BarrierControl/GeneratedCommands/GoToPercent * * @param unid The UNID of the node that sent us the command. * @@ -116108,19 +121789,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_response_command( +void uic_mqtt_dotdot_barrier_control_publish_generated_go_to_percent_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_all_rfid_codes_response_fields_t *fields + const uic_mqtt_dotdot_barrier_control_command_go_to_percent_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearAllRFIDCodesResponse"; + topic += "BarrierControl/GeneratedCommands/GoToPercent"; std::string payload = - get_json_payload_for_door_lock_clear_all_rfid_codes_response_command( + get_json_payload_for_barrier_control_go_to_percent_command( fields); // Publish our command @@ -116130,34 +121811,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_all_rfid_codes_response_c false); } /** - * @brief Publishes an incoming/generated SetUser command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated Stop command for + * the BarrierControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetUser + * ucl/by-unid/UNID/epID/BarrierControl/GeneratedCommands/Stop * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_user_command( +void uic_mqtt_dotdot_barrier_control_publish_generated_stop_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_user_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetUser"; + topic += "BarrierControl/GeneratedCommands/Stop"; std::string payload = - get_json_payload_for_door_lock_set_user_command( - fields); + get_json_payload_for_barrier_control_stop_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116166,11 +121843,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_command( false); } /** - * @brief Publishes an incoming/generated GetUser command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated SetpointRaiseOrLower command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUser + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/SetpointRaiseOrLower * * @param unid The UNID of the node that sent us the command. * @@ -116180,19 +121857,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_user_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_user_command( +void uic_mqtt_dotdot_thermostat_publish_generated_setpoint_raise_or_lower_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_user_fields_t *fields + const uic_mqtt_dotdot_thermostat_command_setpoint_raise_or_lower_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetUser"; + topic += "Thermostat/GeneratedCommands/SetpointRaiseOrLower"; std::string payload = - get_json_payload_for_door_lock_get_user_command( + get_json_payload_for_thermostat_setpoint_raise_or_lower_command( fields); // Publish our command @@ -116202,30 +121879,34 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_command( false); } /** - * @brief Publishes an incoming/generated GetUserResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GetWeeklyScheduleResponse command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetUserResponse + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetWeeklyScheduleResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_user_response_command( +void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_thermostat_command_get_weekly_schedule_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetUserResponse"; + topic += "Thermostat/GeneratedCommands/GetWeeklyScheduleResponse"; std::string payload = - get_json_payload_for_door_lock_get_user_response_command( - ); + get_json_payload_for_thermostat_get_weekly_schedule_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116234,11 +121915,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_response_command( false); } /** - * @brief Publishes an incoming/generated ClearUser command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated SetWeeklySchedule command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearUser + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/SetWeeklySchedule * * @param unid The UNID of the node that sent us the command. * @@ -116248,19 +121929,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_user_response_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_user_command( +void uic_mqtt_dotdot_thermostat_publish_generated_set_weekly_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_user_fields_t *fields + const uic_mqtt_dotdot_thermostat_command_set_weekly_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearUser"; + topic += "Thermostat/GeneratedCommands/SetWeeklySchedule"; std::string payload = - get_json_payload_for_door_lock_clear_user_command( + get_json_payload_for_thermostat_set_weekly_schedule_command( fields); // Publish our command @@ -116270,11 +121951,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_user_command( false); } /** - * @brief Publishes an incoming/generated OperatingEventNotification command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GetRelayStatusLogResponse command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/OperatingEventNotification + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetRelayStatusLogResponse * * @param unid The UNID of the node that sent us the command. * @@ -116284,19 +121965,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_user_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_operating_event_notification_command( +void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_operating_event_notification_fields_t *fields + const uic_mqtt_dotdot_thermostat_command_get_relay_status_log_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/OperatingEventNotification"; + topic += "Thermostat/GeneratedCommands/GetRelayStatusLogResponse"; std::string payload = - get_json_payload_for_door_lock_operating_event_notification_command( + get_json_payload_for_thermostat_get_relay_status_log_response_command( fields); // Publish our command @@ -116306,11 +121987,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_operating_event_notification_co false); } /** - * @brief Publishes an incoming/generated ProgrammingEventNotification command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GetWeeklySchedule command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ProgrammingEventNotification + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetWeeklySchedule * * @param unid The UNID of the node that sent us the command. * @@ -116320,19 +122001,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_operating_event_notification_co * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_programming_event_notification_command( +void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_programming_event_notification_fields_t *fields + const uic_mqtt_dotdot_thermostat_command_get_weekly_schedule_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ProgrammingEventNotification"; + topic += "Thermostat/GeneratedCommands/GetWeeklySchedule"; std::string payload = - get_json_payload_for_door_lock_programming_event_notification_command( + get_json_payload_for_thermostat_get_weekly_schedule_command( fields); // Publish our command @@ -116342,34 +122023,30 @@ void uic_mqtt_dotdot_door_lock_publish_generated_programming_event_notification_ false); } /** - * @brief Publishes an incoming/generated SetCredential command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated ClearWeeklySchedule command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetCredential + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/ClearWeeklySchedule * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_command( +void uic_mqtt_dotdot_thermostat_publish_generated_clear_weekly_schedule_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_set_credential_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetCredential"; + topic += "Thermostat/GeneratedCommands/ClearWeeklySchedule"; std::string payload = - get_json_payload_for_door_lock_set_credential_command( - fields); + get_json_payload_for_thermostat_clear_weekly_schedule_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116378,11 +122055,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_command( false); } /** - * @brief Publishes an incoming/generated SetCredentialResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated GetRelayStatusLog command for + * the Thermostat cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/SetCredentialResponse + * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetRelayStatusLog * * @param unid The UNID of the node that sent us the command. * @@ -116390,17 +122067,17 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_command( * * */ -void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_response_command( +void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/SetCredentialResponse"; + topic += "Thermostat/GeneratedCommands/GetRelayStatusLog"; std::string payload = - get_json_payload_for_door_lock_set_credential_response_command( + get_json_payload_for_thermostat_get_relay_status_log_command( ); // Publish our command @@ -116410,11 +122087,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_response_command false); } /** - * @brief Publishes an incoming/generated GetCredentialStatus command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated MoveToHue command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetCredentialStatus + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToHue * * @param unid The UNID of the node that sent us the command. * @@ -116424,19 +122101,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_set_credential_response_command * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_to_hue_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_get_credential_status_fields_t *fields + const uic_mqtt_dotdot_color_control_command_move_to_hue_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetCredentialStatus"; + topic += "ColorControl/GeneratedCommands/MoveToHue"; std::string payload = - get_json_payload_for_door_lock_get_credential_status_command( + get_json_payload_for_color_control_move_to_hue_command( fields); // Publish our command @@ -116446,30 +122123,34 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_command( false); } /** - * @brief Publishes an incoming/generated GetCredentialStatusResponse command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated MoveHue command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/GetCredentialStatusResponse + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveHue * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_response_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_hue_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_color_control_command_move_hue_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/GetCredentialStatusResponse"; + topic += "ColorControl/GeneratedCommands/MoveHue"; std::string payload = - get_json_payload_for_door_lock_get_credential_status_response_command( - ); + get_json_payload_for_color_control_move_hue_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116478,11 +122159,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_response_ false); } /** - * @brief Publishes an incoming/generated ClearCredential command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated StepHue command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/ClearCredential + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepHue * * @param unid The UNID of the node that sent us the command. * @@ -116492,19 +122173,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_get_credential_status_response_ * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_clear_credential_command( +void uic_mqtt_dotdot_color_control_publish_generated_step_hue_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_clear_credential_fields_t *fields + const uic_mqtt_dotdot_color_control_command_step_hue_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/ClearCredential"; + topic += "ColorControl/GeneratedCommands/StepHue"; std::string payload = - get_json_payload_for_door_lock_clear_credential_command( + get_json_payload_for_color_control_step_hue_command( fields); // Publish our command @@ -116514,11 +122195,11 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_credential_command( false); } /** - * @brief Publishes an incoming/generated UnboltDoor command for - * the DoorLock cluster. + * @brief Publishes an incoming/generated MoveToSaturation command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/DoorLock/GeneratedCommands/UnboltDoor + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToSaturation * * @param unid The UNID of the node that sent us the command. * @@ -116528,19 +122209,19 @@ void uic_mqtt_dotdot_door_lock_publish_generated_clear_credential_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_door_lock_publish_generated_unbolt_door_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_to_saturation_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_door_lock_command_unbolt_door_fields_t *fields + const uic_mqtt_dotdot_color_control_command_move_to_saturation_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "DoorLock/GeneratedCommands/UnboltDoor"; + topic += "ColorControl/GeneratedCommands/MoveToSaturation"; std::string payload = - get_json_payload_for_door_lock_unbolt_door_command( + get_json_payload_for_color_control_move_to_saturation_command( fields); // Publish our command @@ -116550,30 +122231,34 @@ void uic_mqtt_dotdot_door_lock_publish_generated_unbolt_door_command( false); } /** - * @brief Publishes an incoming/generated UpOrOpen command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated MoveSaturation command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/UpOrOpen + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveSaturation * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_window_covering_publish_generated_up_or_open_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_saturation_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_color_control_command_move_saturation_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/UpOrOpen"; + topic += "ColorControl/GeneratedCommands/MoveSaturation"; std::string payload = - get_json_payload_for_window_covering_up_or_open_command( - ); + get_json_payload_for_color_control_move_saturation_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116582,30 +122267,34 @@ void uic_mqtt_dotdot_window_covering_publish_generated_up_or_open_command( false); } /** - * @brief Publishes an incoming/generated DownOrClose command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated StepSaturation command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/DownOrClose + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepSaturation * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_window_covering_publish_generated_down_or_close_command( +void uic_mqtt_dotdot_color_control_publish_generated_step_saturation_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_color_control_command_step_saturation_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/DownOrClose"; + topic += "ColorControl/GeneratedCommands/StepSaturation"; std::string payload = - get_json_payload_for_window_covering_down_or_close_command( - ); + get_json_payload_for_color_control_step_saturation_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116614,30 +122303,34 @@ void uic_mqtt_dotdot_window_covering_publish_generated_down_or_close_command( false); } /** - * @brief Publishes an incoming/generated Stop command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated MoveToHueAndSaturation command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/Stop + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToHueAndSaturation * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_window_covering_publish_generated_stop_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_to_hue_and_saturation_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_color_control_command_move_to_hue_and_saturation_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/Stop"; + topic += "ColorControl/GeneratedCommands/MoveToHueAndSaturation"; std::string payload = - get_json_payload_for_window_covering_stop_command( - ); + get_json_payload_for_color_control_move_to_hue_and_saturation_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116646,11 +122339,11 @@ void uic_mqtt_dotdot_window_covering_publish_generated_stop_command( false); } /** - * @brief Publishes an incoming/generated GoToLiftValue command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated MoveToColor command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToLiftValue + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToColor * * @param unid The UNID of the node that sent us the command. * @@ -116660,19 +122353,19 @@ void uic_mqtt_dotdot_window_covering_publish_generated_stop_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_value_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_window_covering_command_go_to_lift_value_fields_t *fields + const uic_mqtt_dotdot_color_control_command_move_to_color_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/GoToLiftValue"; + topic += "ColorControl/GeneratedCommands/MoveToColor"; std::string payload = - get_json_payload_for_window_covering_go_to_lift_value_command( + get_json_payload_for_color_control_move_to_color_command( fields); // Publish our command @@ -116682,11 +122375,11 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_value_command( false); } /** - * @brief Publishes an incoming/generated GoToLiftPercentage command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated MoveColor command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToLiftPercentage + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveColor * * @param unid The UNID of the node that sent us the command. * @@ -116696,19 +122389,19 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_value_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_percentage_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_color_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_window_covering_command_go_to_lift_percentage_fields_t *fields + const uic_mqtt_dotdot_color_control_command_move_color_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/GoToLiftPercentage"; + topic += "ColorControl/GeneratedCommands/MoveColor"; std::string payload = - get_json_payload_for_window_covering_go_to_lift_percentage_command( + get_json_payload_for_color_control_move_color_command( fields); // Publish our command @@ -116718,11 +122411,11 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_percentage_com false); } /** - * @brief Publishes an incoming/generated GoToTiltValue command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated StepColor command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToTiltValue + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepColor * * @param unid The UNID of the node that sent us the command. * @@ -116732,19 +122425,19 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_lift_percentage_com * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_value_command( +void uic_mqtt_dotdot_color_control_publish_generated_step_color_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_window_covering_command_go_to_tilt_value_fields_t *fields + const uic_mqtt_dotdot_color_control_command_step_color_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/GoToTiltValue"; + topic += "ColorControl/GeneratedCommands/StepColor"; std::string payload = - get_json_payload_for_window_covering_go_to_tilt_value_command( + get_json_payload_for_color_control_step_color_command( fields); // Publish our command @@ -116754,11 +122447,11 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_value_command( false); } /** - * @brief Publishes an incoming/generated GoToTiltPercentage command for - * the WindowCovering cluster. + * @brief Publishes an incoming/generated MoveToColorTemperature command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/WindowCovering/GeneratedCommands/GoToTiltPercentage + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToColorTemperature * * @param unid The UNID of the node that sent us the command. * @@ -116768,19 +122461,19 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_value_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_percentage_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_temperature_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_window_covering_command_go_to_tilt_percentage_fields_t *fields + const uic_mqtt_dotdot_color_control_command_move_to_color_temperature_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "WindowCovering/GeneratedCommands/GoToTiltPercentage"; + topic += "ColorControl/GeneratedCommands/MoveToColorTemperature"; std::string payload = - get_json_payload_for_window_covering_go_to_tilt_percentage_command( + get_json_payload_for_color_control_move_to_color_temperature_command( fields); // Publish our command @@ -116790,11 +122483,11 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_percentage_com false); } /** - * @brief Publishes an incoming/generated GoToPercent command for - * the BarrierControl cluster. + * @brief Publishes an incoming/generated EnhancedMoveToHue command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/BarrierControl/GeneratedCommands/GoToPercent + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedMoveToHue * * @param unid The UNID of the node that sent us the command. * @@ -116804,19 +122497,19 @@ void uic_mqtt_dotdot_window_covering_publish_generated_go_to_tilt_percentage_com * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_barrier_control_publish_generated_go_to_percent_command( +void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_to_hue_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_barrier_control_command_go_to_percent_fields_t *fields + const uic_mqtt_dotdot_color_control_command_enhanced_move_to_hue_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "BarrierControl/GeneratedCommands/GoToPercent"; + topic += "ColorControl/GeneratedCommands/EnhancedMoveToHue"; std::string payload = - get_json_payload_for_barrier_control_go_to_percent_command( + get_json_payload_for_color_control_enhanced_move_to_hue_command( fields); // Publish our command @@ -116826,30 +122519,34 @@ void uic_mqtt_dotdot_barrier_control_publish_generated_go_to_percent_command( false); } /** - * @brief Publishes an incoming/generated Stop command for - * the BarrierControl cluster. + * @brief Publishes an incoming/generated EnhancedMoveHue command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/BarrierControl/GeneratedCommands/Stop + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedMoveHue * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_barrier_control_publish_generated_stop_command( +void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_hue_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_color_control_command_enhanced_move_hue_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "BarrierControl/GeneratedCommands/Stop"; + topic += "ColorControl/GeneratedCommands/EnhancedMoveHue"; std::string payload = - get_json_payload_for_barrier_control_stop_command( - ); + get_json_payload_for_color_control_enhanced_move_hue_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -116858,11 +122555,11 @@ void uic_mqtt_dotdot_barrier_control_publish_generated_stop_command( false); } /** - * @brief Publishes an incoming/generated SetpointRaiseOrLower command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated EnhancedStepHue command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/SetpointRaiseOrLower + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedStepHue * * @param unid The UNID of the node that sent us the command. * @@ -116872,19 +122569,19 @@ void uic_mqtt_dotdot_barrier_control_publish_generated_stop_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_thermostat_publish_generated_setpoint_raise_or_lower_command( +void uic_mqtt_dotdot_color_control_publish_generated_enhanced_step_hue_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_thermostat_command_setpoint_raise_or_lower_fields_t *fields + const uic_mqtt_dotdot_color_control_command_enhanced_step_hue_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/SetpointRaiseOrLower"; + topic += "ColorControl/GeneratedCommands/EnhancedStepHue"; std::string payload = - get_json_payload_for_thermostat_setpoint_raise_or_lower_command( + get_json_payload_for_color_control_enhanced_step_hue_command( fields); // Publish our command @@ -116894,11 +122591,11 @@ void uic_mqtt_dotdot_thermostat_publish_generated_setpoint_raise_or_lower_comman false); } /** - * @brief Publishes an incoming/generated GetWeeklyScheduleResponse command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated EnhancedMoveToHueAndSaturation command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetWeeklyScheduleResponse + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedMoveToHueAndSaturation * * @param unid The UNID of the node that sent us the command. * @@ -116908,19 +122605,19 @@ void uic_mqtt_dotdot_thermostat_publish_generated_setpoint_raise_or_lower_comman * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_response_command( +void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_to_hue_and_saturation_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_thermostat_command_get_weekly_schedule_response_fields_t *fields + const uic_mqtt_dotdot_color_control_command_enhanced_move_to_hue_and_saturation_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/GetWeeklyScheduleResponse"; + topic += "ColorControl/GeneratedCommands/EnhancedMoveToHueAndSaturation"; std::string payload = - get_json_payload_for_thermostat_get_weekly_schedule_response_command( + get_json_payload_for_color_control_enhanced_move_to_hue_and_saturation_command( fields); // Publish our command @@ -116930,11 +122627,11 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_response_c false); } /** - * @brief Publishes an incoming/generated SetWeeklySchedule command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated ColorLoopSet command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/SetWeeklySchedule + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/ColorLoopSet * * @param unid The UNID of the node that sent us the command. * @@ -116944,19 +122641,19 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_response_c * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_thermostat_publish_generated_set_weekly_schedule_command( +void uic_mqtt_dotdot_color_control_publish_generated_color_loop_set_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_thermostat_command_set_weekly_schedule_fields_t *fields + const uic_mqtt_dotdot_color_control_command_color_loop_set_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/SetWeeklySchedule"; + topic += "ColorControl/GeneratedCommands/ColorLoopSet"; std::string payload = - get_json_payload_for_thermostat_set_weekly_schedule_command( + get_json_payload_for_color_control_color_loop_set_command( fields); // Publish our command @@ -116966,11 +122663,11 @@ void uic_mqtt_dotdot_thermostat_publish_generated_set_weekly_schedule_command( false); } /** - * @brief Publishes an incoming/generated GetRelayStatusLogResponse command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated StopMoveStep command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetRelayStatusLogResponse + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StopMoveStep * * @param unid The UNID of the node that sent us the command. * @@ -116980,19 +122677,19 @@ void uic_mqtt_dotdot_thermostat_publish_generated_set_weekly_schedule_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_response_command( +void uic_mqtt_dotdot_color_control_publish_generated_stop_move_step_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_thermostat_command_get_relay_status_log_response_fields_t *fields + const uic_mqtt_dotdot_color_control_command_stop_move_step_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/GetRelayStatusLogResponse"; + topic += "ColorControl/GeneratedCommands/StopMoveStep"; std::string payload = - get_json_payload_for_thermostat_get_relay_status_log_response_command( + get_json_payload_for_color_control_stop_move_step_command( fields); // Publish our command @@ -117002,11 +122699,11 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_response_ false); } /** - * @brief Publishes an incoming/generated GetWeeklySchedule command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated MoveColorTemperature command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetWeeklySchedule + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveColorTemperature * * @param unid The UNID of the node that sent us the command. * @@ -117016,19 +122713,19 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_response_ * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_command( +void uic_mqtt_dotdot_color_control_publish_generated_move_color_temperature_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_thermostat_command_get_weekly_schedule_fields_t *fields + const uic_mqtt_dotdot_color_control_command_move_color_temperature_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/GetWeeklySchedule"; + topic += "ColorControl/GeneratedCommands/MoveColorTemperature"; std::string payload = - get_json_payload_for_thermostat_get_weekly_schedule_command( + get_json_payload_for_color_control_move_color_temperature_command( fields); // Publish our command @@ -117038,30 +122735,34 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_weekly_schedule_command( false); } /** - * @brief Publishes an incoming/generated ClearWeeklySchedule command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated StepColorTemperature command for + * the ColorControl cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/ClearWeeklySchedule + * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepColorTemperature * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_thermostat_publish_generated_clear_weekly_schedule_command( +void uic_mqtt_dotdot_color_control_publish_generated_step_color_temperature_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_color_control_command_step_color_temperature_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/ClearWeeklySchedule"; + topic += "ColorControl/GeneratedCommands/StepColorTemperature"; std::string payload = - get_json_payload_for_thermostat_clear_weekly_schedule_command( - ); + get_json_payload_for_color_control_step_color_temperature_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117070,30 +122771,34 @@ void uic_mqtt_dotdot_thermostat_publish_generated_clear_weekly_schedule_command( false); } /** - * @brief Publishes an incoming/generated GetRelayStatusLog command for - * the Thermostat cluster. + * @brief Publishes an incoming/generated ZoneEnrollResponse command for + * the IASZone cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Thermostat/GeneratedCommands/GetRelayStatusLog + * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/ZoneEnrollResponse * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_command( +void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_response_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_ias_zone_command_zone_enroll_response_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Thermostat/GeneratedCommands/GetRelayStatusLog"; + topic += "IASZone/GeneratedCommands/ZoneEnrollResponse"; std::string payload = - get_json_payload_for_thermostat_get_relay_status_log_command( - ); + get_json_payload_for_ias_zone_zone_enroll_response_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117102,11 +122807,11 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_command( false); } /** - * @brief Publishes an incoming/generated MoveToHue command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated ZoneStatusChangeNotification command for + * the IASZone cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToHue + * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/ZoneStatusChangeNotification * * @param unid The UNID of the node that sent us the command. * @@ -117116,19 +122821,19 @@ void uic_mqtt_dotdot_thermostat_publish_generated_get_relay_status_log_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_to_hue_command( +void uic_mqtt_dotdot_ias_zone_publish_generated_zone_status_change_notification_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_to_hue_fields_t *fields + const uic_mqtt_dotdot_ias_zone_command_zone_status_change_notification_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveToHue"; + topic += "IASZone/GeneratedCommands/ZoneStatusChangeNotification"; std::string payload = - get_json_payload_for_color_control_move_to_hue_command( + get_json_payload_for_ias_zone_zone_status_change_notification_command( fields); // Publish our command @@ -117138,34 +122843,30 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_hue_command( false); } /** - * @brief Publishes an incoming/generated MoveHue command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated InitiateNormalOperationMode command for + * the IASZone cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveHue + * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/InitiateNormalOperationMode * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_hue_command( +void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_normal_operation_mode_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_hue_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveHue"; + topic += "IASZone/GeneratedCommands/InitiateNormalOperationMode"; std::string payload = - get_json_payload_for_color_control_move_hue_command( - fields); + get_json_payload_for_ias_zone_initiate_normal_operation_mode_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117174,11 +122875,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_hue_command( false); } /** - * @brief Publishes an incoming/generated StepHue command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated ZoneEnrollRequest command for + * the IASZone cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepHue + * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/ZoneEnrollRequest * * @param unid The UNID of the node that sent us the command. * @@ -117188,19 +122889,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_hue_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_step_hue_command( +void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_request_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_step_hue_fields_t *fields + const uic_mqtt_dotdot_ias_zone_command_zone_enroll_request_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/StepHue"; + topic += "IASZone/GeneratedCommands/ZoneEnrollRequest"; std::string payload = - get_json_payload_for_color_control_step_hue_command( + get_json_payload_for_ias_zone_zone_enroll_request_command( fields); // Publish our command @@ -117210,11 +122911,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_hue_command( false); } /** - * @brief Publishes an incoming/generated MoveToSaturation command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated InitiateTestMode command for + * the IASZone cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToSaturation + * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/InitiateTestMode * * @param unid The UNID of the node that sent us the command. * @@ -117224,19 +122925,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_hue_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_to_saturation_command( +void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_test_mode_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_to_saturation_fields_t *fields + const uic_mqtt_dotdot_ias_zone_command_initiate_test_mode_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveToSaturation"; + topic += "IASZone/GeneratedCommands/InitiateTestMode"; std::string payload = - get_json_payload_for_color_control_move_to_saturation_command( + get_json_payload_for_ias_zone_initiate_test_mode_command( fields); // Publish our command @@ -117246,11 +122947,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_saturation_command( false); } /** - * @brief Publishes an incoming/generated MoveSaturation command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated StartWarning command for + * the IASWD cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveSaturation + * ucl/by-unid/UNID/epID/IASWD/GeneratedCommands/StartWarning * * @param unid The UNID of the node that sent us the command. * @@ -117260,19 +122961,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_saturation_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_saturation_command( +void uic_mqtt_dotdot_iaswd_publish_generated_start_warning_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_saturation_fields_t *fields + const uic_mqtt_dotdot_iaswd_command_start_warning_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveSaturation"; + topic += "IASWD/GeneratedCommands/StartWarning"; std::string payload = - get_json_payload_for_color_control_move_saturation_command( + get_json_payload_for_iaswd_start_warning_command( fields); // Publish our command @@ -117282,11 +122983,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_saturation_command( false); } /** - * @brief Publishes an incoming/generated StepSaturation command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated Squawk command for + * the IASWD cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepSaturation + * ucl/by-unid/UNID/epID/IASWD/GeneratedCommands/Squawk * * @param unid The UNID of the node that sent us the command. * @@ -117296,19 +122997,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_saturation_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_step_saturation_command( +void uic_mqtt_dotdot_iaswd_publish_generated_squawk_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_step_saturation_fields_t *fields + const uic_mqtt_dotdot_iaswd_command_squawk_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/StepSaturation"; + topic += "IASWD/GeneratedCommands/Squawk"; std::string payload = - get_json_payload_for_color_control_step_saturation_command( + get_json_payload_for_iaswd_squawk_command( fields); // Publish our command @@ -117318,11 +123019,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_saturation_command( false); } /** - * @brief Publishes an incoming/generated MoveToHueAndSaturation command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated GetProfileInfoResponse command for + * the ElectricalMeasurement cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToHueAndSaturation + * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetProfileInfoResponse * * @param unid The UNID of the node that sent us the command. * @@ -117332,19 +123033,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_saturation_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_to_hue_and_saturation_command( +void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_to_hue_and_saturation_fields_t *fields + const uic_mqtt_dotdot_electrical_measurement_command_get_profile_info_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveToHueAndSaturation"; + topic += "ElectricalMeasurement/GeneratedCommands/GetProfileInfoResponse"; std::string payload = - get_json_payload_for_color_control_move_to_hue_and_saturation_command( + get_json_payload_for_electrical_measurement_get_profile_info_response_command( fields); // Publish our command @@ -117354,34 +123055,30 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_hue_and_saturation_ false); } /** - * @brief Publishes an incoming/generated MoveToColor command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated GetProfileInfo command for + * the ElectricalMeasurement cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToColor + * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetProfileInfo * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_command( +void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_to_color_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveToColor"; + topic += "ElectricalMeasurement/GeneratedCommands/GetProfileInfo"; std::string payload = - get_json_payload_for_color_control_move_to_color_command( - fields); + get_json_payload_for_electrical_measurement_get_profile_info_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117390,11 +123087,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_command( false); } /** - * @brief Publishes an incoming/generated MoveColor command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated GetMeasurementProfileResponse command for + * the ElectricalMeasurement cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveColor + * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetMeasurementProfileResponse * * @param unid The UNID of the node that sent us the command. * @@ -117404,19 +123101,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_color_command( +void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_profile_response_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_color_fields_t *fields + const uic_mqtt_dotdot_electrical_measurement_command_get_measurement_profile_response_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveColor"; + topic += "ElectricalMeasurement/GeneratedCommands/GetMeasurementProfileResponse"; std::string payload = - get_json_payload_for_color_control_move_color_command( + get_json_payload_for_electrical_measurement_get_measurement_profile_response_command( fields); // Publish our command @@ -117426,11 +123123,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_color_command( false); } /** - * @brief Publishes an incoming/generated StepColor command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated GetMeasurementProfile command for + * the ElectricalMeasurement cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepColor + * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetMeasurementProfile * * @param unid The UNID of the node that sent us the command. * @@ -117440,19 +123137,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_color_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_step_color_command( +void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_profile_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_step_color_fields_t *fields + const uic_mqtt_dotdot_electrical_measurement_command_get_measurement_profile_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/StepColor"; + topic += "ElectricalMeasurement/GeneratedCommands/GetMeasurementProfile"; std::string payload = - get_json_payload_for_color_control_step_color_command( + get_json_payload_for_electrical_measurement_get_measurement_profile_command( fields); // Publish our command @@ -117462,33 +123159,29 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_color_command( false); } /** - * @brief Publishes an incoming/generated MoveToColorTemperature command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated TxReport command for + * the ProtocolController-RFTelemetry cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveToColorTemperature + * ucl/by-unid/UNID/ProtocolController/RFTelemetry/GeneratedCommands/TxReport * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * * * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_temperature_command( +void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_generated_tx_report_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_to_color_temperature_fields_t *fields + const uic_mqtt_dotdot_protocol_controller_rf_telemetry_command_tx_report_fields_t *fields ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveToColorTemperature"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "ProtocolController/RFTelemetry/GeneratedCommands/TxReport"; std::string payload = - get_json_payload_for_color_control_move_to_color_temperature_command( + get_json_payload_for_protocol_controller_rf_telemetry_tx_report_command( fields); // Publish our command @@ -117498,34 +123191,26 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_to_color_temperature_c false); } /** - * @brief Publishes an incoming/generated EnhancedMoveToHue command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated Remove command for + * the State cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedMoveToHue + * ucl/by-unid/UNID/State/GeneratedCommands/Remove * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * - * - * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_to_hue_command( - const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_enhanced_move_to_hue_fields_t *fields - +void uic_mqtt_dotdot_state_publish_generated_remove_command( + const dotdot_unid_t unid ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/EnhancedMoveToHue"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "State/GeneratedCommands/Remove"; std::string payload = - get_json_payload_for_color_control_enhanced_move_to_hue_command( - fields); + get_json_payload_for_state_remove_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117534,34 +123219,26 @@ void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_to_hue_comman false); } /** - * @brief Publishes an incoming/generated EnhancedMoveHue command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated RemoveOffline command for + * the State cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedMoveHue + * ucl/by-unid/UNID/State/GeneratedCommands/RemoveOffline * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * - * - * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_hue_command( - const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_enhanced_move_hue_fields_t *fields - +void uic_mqtt_dotdot_state_publish_generated_remove_offline_command( + const dotdot_unid_t unid ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/EnhancedMoveHue"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "State/GeneratedCommands/RemoveOffline"; std::string payload = - get_json_payload_for_color_control_enhanced_move_hue_command( - fields); + get_json_payload_for_state_remove_offline_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117570,34 +123247,26 @@ void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_hue_command( false); } /** - * @brief Publishes an incoming/generated EnhancedStepHue command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated DiscoverNeighbors command for + * the State cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedStepHue + * ucl/by-unid/UNID/State/GeneratedCommands/DiscoverNeighbors * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * - * - * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_enhanced_step_hue_command( - const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_enhanced_step_hue_fields_t *fields - +void uic_mqtt_dotdot_state_publish_generated_discover_neighbors_command( + const dotdot_unid_t unid ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/EnhancedStepHue"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "State/GeneratedCommands/DiscoverNeighbors"; std::string payload = - get_json_payload_for_color_control_enhanced_step_hue_command( - fields); + get_json_payload_for_state_discover_neighbors_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117606,34 +123275,26 @@ void uic_mqtt_dotdot_color_control_publish_generated_enhanced_step_hue_command( false); } /** - * @brief Publishes an incoming/generated EnhancedMoveToHueAndSaturation command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated Interview command for + * the State cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/EnhancedMoveToHueAndSaturation + * ucl/by-unid/UNID/State/GeneratedCommands/Interview * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * - * - * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_to_hue_and_saturation_command( - const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_enhanced_move_to_hue_and_saturation_fields_t *fields - +void uic_mqtt_dotdot_state_publish_generated_interview_command( + const dotdot_unid_t unid ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/EnhancedMoveToHueAndSaturation"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "State/GeneratedCommands/Interview"; std::string payload = - get_json_payload_for_color_control_enhanced_move_to_hue_and_saturation_command( - fields); + get_json_payload_for_state_interview_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117642,34 +123303,26 @@ void uic_mqtt_dotdot_color_control_publish_generated_enhanced_move_to_hue_and_sa false); } /** - * @brief Publishes an incoming/generated ColorLoopSet command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated DiscoverSecurity command for + * the State cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/ColorLoopSet + * ucl/by-unid/UNID/State/GeneratedCommands/DiscoverSecurity * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * - * - * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_color_loop_set_command( - const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_color_loop_set_fields_t *fields - +void uic_mqtt_dotdot_state_publish_generated_discover_security_command( + const dotdot_unid_t unid ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/ColorLoopSet"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "State/GeneratedCommands/DiscoverSecurity"; std::string payload = - get_json_payload_for_color_control_color_loop_set_command( - fields); + get_json_payload_for_state_discover_security_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117678,11 +123331,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_color_loop_set_command( false); } /** - * @brief Publishes an incoming/generated StopMoveStep command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated Bind command for + * the Binding cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StopMoveStep + * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/Bind * * @param unid The UNID of the node that sent us the command. * @@ -117692,19 +123345,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_color_loop_set_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_stop_move_step_command( +void uic_mqtt_dotdot_binding_publish_generated_bind_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_stop_move_step_fields_t *fields + const uic_mqtt_dotdot_binding_command_bind_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/StopMoveStep"; + topic += "Binding/GeneratedCommands/Bind"; std::string payload = - get_json_payload_for_color_control_stop_move_step_command( + get_json_payload_for_binding_bind_command( fields); // Publish our command @@ -117714,11 +123367,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_stop_move_step_command( false); } /** - * @brief Publishes an incoming/generated MoveColorTemperature command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated Unbind command for + * the Binding cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/MoveColorTemperature + * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/Unbind * * @param unid The UNID of the node that sent us the command. * @@ -117728,19 +123381,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_stop_move_step_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_move_color_temperature_command( +void uic_mqtt_dotdot_binding_publish_generated_unbind_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_move_color_temperature_fields_t *fields + const uic_mqtt_dotdot_binding_command_unbind_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/MoveColorTemperature"; + topic += "Binding/GeneratedCommands/Unbind"; std::string payload = - get_json_payload_for_color_control_move_color_temperature_command( + get_json_payload_for_binding_unbind_command( fields); // Publish our command @@ -117750,11 +123403,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_color_temperature_comm false); } /** - * @brief Publishes an incoming/generated StepColorTemperature command for - * the ColorControl cluster. + * @brief Publishes an incoming/generated BindToProtocolController command for + * the Binding cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ColorControl/GeneratedCommands/StepColorTemperature + * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/BindToProtocolController * * @param unid The UNID of the node that sent us the command. * @@ -117764,19 +123417,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_move_color_temperature_comm * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_color_control_publish_generated_step_color_temperature_command( +void uic_mqtt_dotdot_binding_publish_generated_bind_to_protocol_controller_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_color_control_command_step_color_temperature_fields_t *fields + const uic_mqtt_dotdot_binding_command_bind_to_protocol_controller_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ColorControl/GeneratedCommands/StepColorTemperature"; + topic += "Binding/GeneratedCommands/BindToProtocolController"; std::string payload = - get_json_payload_for_color_control_step_color_temperature_command( + get_json_payload_for_binding_bind_to_protocol_controller_command( fields); // Publish our command @@ -117786,11 +123439,11 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_color_temperature_comm false); } /** - * @brief Publishes an incoming/generated ZoneEnrollResponse command for - * the IASZone cluster. + * @brief Publishes an incoming/generated UnbindFromProtocolController command for + * the Binding cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/ZoneEnrollResponse + * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/UnbindFromProtocolController * * @param unid The UNID of the node that sent us the command. * @@ -117800,19 +123453,19 @@ void uic_mqtt_dotdot_color_control_publish_generated_step_color_temperature_comm * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_response_command( +void uic_mqtt_dotdot_binding_publish_generated_unbind_from_protocol_controller_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_ias_zone_command_zone_enroll_response_fields_t *fields + const uic_mqtt_dotdot_binding_command_unbind_from_protocol_controller_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "IASZone/GeneratedCommands/ZoneEnrollResponse"; + topic += "Binding/GeneratedCommands/UnbindFromProtocolController"; std::string payload = - get_json_payload_for_ias_zone_zone_enroll_response_command( + get_json_payload_for_binding_unbind_from_protocol_controller_command( fields); // Publish our command @@ -117822,33 +123475,29 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_response_command( false); } /** - * @brief Publishes an incoming/generated ZoneStatusChangeNotification command for - * the IASZone cluster. + * @brief Publishes an incoming/generated LogEntry command for + * the ApplicationMonitoring cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/ZoneStatusChangeNotification + * ucl/by-unid/UNID/ApplicationMonitoring/GeneratedCommands/LogEntry * * @param unid The UNID of the node that sent us the command. * - * @param endpoint The Endpoint ID of the node that sent us the command. - * * * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_ias_zone_publish_generated_zone_status_change_notification_command( +void uic_mqtt_dotdot_application_monitoring_publish_generated_log_entry_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_ias_zone_command_zone_status_change_notification_fields_t *fields + const uic_mqtt_dotdot_application_monitoring_command_log_entry_fields_t *fields ) { // Create the topic - std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + - std::to_string(endpoint) + "/"; - topic += "IASZone/GeneratedCommands/ZoneStatusChangeNotification"; + std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; + topic += "ApplicationMonitoring/GeneratedCommands/LogEntry"; std::string payload = - get_json_payload_for_ias_zone_zone_status_change_notification_command( + get_json_payload_for_application_monitoring_log_entry_command( fields); // Publish our command @@ -117858,30 +123507,34 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_zone_status_change_notification_ false); } /** - * @brief Publishes an incoming/generated InitiateNormalOperationMode command for - * the IASZone cluster. + * @brief Publishes an incoming/generated DiscoverParameter command for + * the ConfigurationParameters cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/InitiateNormalOperationMode + * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/DiscoverParameter * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_normal_operation_mode_command( +void uic_mqtt_dotdot_configuration_parameters_publish_generated_discover_parameter_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_configuration_parameters_command_discover_parameter_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "IASZone/GeneratedCommands/InitiateNormalOperationMode"; + topic += "ConfigurationParameters/GeneratedCommands/DiscoverParameter"; std::string payload = - get_json_payload_for_ias_zone_initiate_normal_operation_mode_command( - ); + get_json_payload_for_configuration_parameters_discover_parameter_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117890,34 +123543,30 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_normal_operation_mode_c false); } /** - * @brief Publishes an incoming/generated ZoneEnrollRequest command for - * the IASZone cluster. + * @brief Publishes an incoming/generated DefaultResetAllParameters command for + * the ConfigurationParameters cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/ZoneEnrollRequest + * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/DefaultResetAllParameters * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_request_command( +void uic_mqtt_dotdot_configuration_parameters_publish_generated_default_reset_all_parameters_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_ias_zone_command_zone_enroll_request_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "IASZone/GeneratedCommands/ZoneEnrollRequest"; + topic += "ConfigurationParameters/GeneratedCommands/DefaultResetAllParameters"; std::string payload = - get_json_payload_for_ias_zone_zone_enroll_request_command( - fields); + get_json_payload_for_configuration_parameters_default_reset_all_parameters_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -117926,11 +123575,11 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_request_command( false); } /** - * @brief Publishes an incoming/generated InitiateTestMode command for - * the IASZone cluster. + * @brief Publishes an incoming/generated SetParameter command for + * the ConfigurationParameters cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASZone/GeneratedCommands/InitiateTestMode + * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/SetParameter * * @param unid The UNID of the node that sent us the command. * @@ -117940,19 +123589,19 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_zone_enroll_request_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_test_mode_command( +void uic_mqtt_dotdot_configuration_parameters_publish_generated_set_parameter_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_ias_zone_command_initiate_test_mode_fields_t *fields + const uic_mqtt_dotdot_configuration_parameters_command_set_parameter_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "IASZone/GeneratedCommands/InitiateTestMode"; + topic += "ConfigurationParameters/GeneratedCommands/SetParameter"; std::string payload = - get_json_payload_for_ias_zone_initiate_test_mode_command( + get_json_payload_for_configuration_parameters_set_parameter_command( fields); // Publish our command @@ -117962,11 +123611,11 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_test_mode_command( false); } /** - * @brief Publishes an incoming/generated StartWarning command for - * the IASWD cluster. + * @brief Publishes an incoming/generated DiscoverParameterRange command for + * the ConfigurationParameters cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASWD/GeneratedCommands/StartWarning + * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/DiscoverParameterRange * * @param unid The UNID of the node that sent us the command. * @@ -117976,19 +123625,19 @@ void uic_mqtt_dotdot_ias_zone_publish_generated_initiate_test_mode_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_iaswd_publish_generated_start_warning_command( +void uic_mqtt_dotdot_configuration_parameters_publish_generated_discover_parameter_range_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_iaswd_command_start_warning_fields_t *fields + const uic_mqtt_dotdot_configuration_parameters_command_discover_parameter_range_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "IASWD/GeneratedCommands/StartWarning"; + topic += "ConfigurationParameters/GeneratedCommands/DiscoverParameterRange"; std::string payload = - get_json_payload_for_iaswd_start_warning_command( + get_json_payload_for_configuration_parameters_discover_parameter_range_command( fields); // Publish our command @@ -117998,11 +123647,11 @@ void uic_mqtt_dotdot_iaswd_publish_generated_start_warning_command( false); } /** - * @brief Publishes an incoming/generated Squawk command for - * the IASWD cluster. + * @brief Publishes an incoming/generated AddUser command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/IASWD/GeneratedCommands/Squawk + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/AddUser * * @param unid The UNID of the node that sent us the command. * @@ -118012,19 +123661,19 @@ void uic_mqtt_dotdot_iaswd_publish_generated_start_warning_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_iaswd_publish_generated_squawk_command( +void uic_mqtt_dotdot_user_credential_publish_generated_add_user_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_iaswd_command_squawk_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "IASWD/GeneratedCommands/Squawk"; + topic += "UserCredential/GeneratedCommands/AddUser"; std::string payload = - get_json_payload_for_iaswd_squawk_command( + get_json_payload_for_user_credential_add_user_command( fields); // Publish our command @@ -118034,11 +123683,11 @@ void uic_mqtt_dotdot_iaswd_publish_generated_squawk_command( false); } /** - * @brief Publishes an incoming/generated GetProfileInfoResponse command for - * the ElectricalMeasurement cluster. + * @brief Publishes an incoming/generated ModifyUser command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetProfileInfoResponse + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/ModifyUser * * @param unid The UNID of the node that sent us the command. * @@ -118048,19 +123697,19 @@ void uic_mqtt_dotdot_iaswd_publish_generated_squawk_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_response_command( +void uic_mqtt_dotdot_user_credential_publish_generated_modify_user_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_electrical_measurement_command_get_profile_info_response_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ElectricalMeasurement/GeneratedCommands/GetProfileInfoResponse"; + topic += "UserCredential/GeneratedCommands/ModifyUser"; std::string payload = - get_json_payload_for_electrical_measurement_get_profile_info_response_command( + get_json_payload_for_user_credential_modify_user_command( fields); // Publish our command @@ -118070,30 +123719,34 @@ void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_r false); } /** - * @brief Publishes an incoming/generated GetProfileInfo command for - * the ElectricalMeasurement cluster. + * @brief Publishes an incoming/generated DeleteUser command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetProfileInfo + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteUser * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * + * @param fields Struct pointer with the fields value of the command + * */ -void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_command( +void uic_mqtt_dotdot_user_credential_publish_generated_delete_user_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ElectricalMeasurement/GeneratedCommands/GetProfileInfo"; + topic += "UserCredential/GeneratedCommands/DeleteUser"; std::string payload = - get_json_payload_for_electrical_measurement_get_profile_info_command( - ); + get_json_payload_for_user_credential_delete_user_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -118102,11 +123755,11 @@ void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_c false); } /** - * @brief Publishes an incoming/generated GetMeasurementProfileResponse command for - * the ElectricalMeasurement cluster. + * @brief Publishes an incoming/generated AddCredential command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetMeasurementProfileResponse + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/AddCredential * * @param unid The UNID of the node that sent us the command. * @@ -118116,19 +123769,19 @@ void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_profile_info_c * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_profile_response_command( +void uic_mqtt_dotdot_user_credential_publish_generated_add_credential_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_electrical_measurement_command_get_measurement_profile_response_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ElectricalMeasurement/GeneratedCommands/GetMeasurementProfileResponse"; + topic += "UserCredential/GeneratedCommands/AddCredential"; std::string payload = - get_json_payload_for_electrical_measurement_get_measurement_profile_response_command( + get_json_payload_for_user_credential_add_credential_command( fields); // Publish our command @@ -118138,11 +123791,11 @@ void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_pr false); } /** - * @brief Publishes an incoming/generated GetMeasurementProfile command for - * the ElectricalMeasurement cluster. + * @brief Publishes an incoming/generated ModifyCredential command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ElectricalMeasurement/GeneratedCommands/GetMeasurementProfile + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/ModifyCredential * * @param unid The UNID of the node that sent us the command. * @@ -118152,19 +123805,19 @@ void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_pr * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_profile_command( +void uic_mqtt_dotdot_user_credential_publish_generated_modify_credential_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_electrical_measurement_command_get_measurement_profile_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ElectricalMeasurement/GeneratedCommands/GetMeasurementProfile"; + topic += "UserCredential/GeneratedCommands/ModifyCredential"; std::string payload = - get_json_payload_for_electrical_measurement_get_measurement_profile_command( + get_json_payload_for_user_credential_modify_credential_command( fields); // Publish our command @@ -118174,29 +123827,33 @@ void uic_mqtt_dotdot_electrical_measurement_publish_generated_get_measurement_pr false); } /** - * @brief Publishes an incoming/generated TxReport command for - * the ProtocolController-RFTelemetry cluster. + * @brief Publishes an incoming/generated DeleteCredential command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/ProtocolController/RFTelemetry/GeneratedCommands/TxReport + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteCredential * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * * * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_generated_tx_report_command( +void uic_mqtt_dotdot_user_credential_publish_generated_delete_credential_command( const dotdot_unid_t unid, - const uic_mqtt_dotdot_protocol_controller_rf_telemetry_command_tx_report_fields_t *fields + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "ProtocolController/RFTelemetry/GeneratedCommands/TxReport"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteCredential"; std::string payload = - get_json_payload_for_protocol_controller_rf_telemetry_tx_report_command( + get_json_payload_for_user_credential_delete_credential_command( fields); // Publish our command @@ -118206,25 +123863,29 @@ void uic_mqtt_dotdot_protocol_controller_rf_telemetry_publish_generated_tx_repor false); } /** - * @brief Publishes an incoming/generated Remove command for - * the State cluster. + * @brief Publishes an incoming/generated DeleteAllUsers command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/State/GeneratedCommands/Remove + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllUsers * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * * */ -void uic_mqtt_dotdot_state_publish_generated_remove_command( - const dotdot_unid_t unid +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_users_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "State/GeneratedCommands/Remove"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllUsers"; std::string payload = - get_json_payload_for_state_remove_command( + get_json_payload_for_user_credential_delete_all_users_command( ); // Publish our command @@ -118234,25 +123895,29 @@ void uic_mqtt_dotdot_state_publish_generated_remove_command( false); } /** - * @brief Publishes an incoming/generated RemoveOffline command for - * the State cluster. + * @brief Publishes an incoming/generated DeleteAllCredentials command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/State/GeneratedCommands/RemoveOffline + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentials * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * * */ -void uic_mqtt_dotdot_state_publish_generated_remove_offline_command( - const dotdot_unid_t unid +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "State/GeneratedCommands/RemoveOffline"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentials"; std::string payload = - get_json_payload_for_state_remove_offline_command( + get_json_payload_for_user_credential_delete_all_credentials_command( ); // Publish our command @@ -118262,26 +123927,34 @@ void uic_mqtt_dotdot_state_publish_generated_remove_offline_command( false); } /** - * @brief Publishes an incoming/generated DiscoverNeighbors command for - * the State cluster. + * @brief Publishes an incoming/generated DeleteAllCredentialsByType command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/State/GeneratedCommands/DiscoverNeighbors + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsByType * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_state_publish_generated_discover_neighbors_command( - const dotdot_unid_t unid +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_by_type_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "State/GeneratedCommands/DiscoverNeighbors"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentialsByType"; std::string payload = - get_json_payload_for_state_discover_neighbors_command( - ); + get_json_payload_for_user_credential_delete_all_credentials_by_type_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -118290,26 +123963,34 @@ void uic_mqtt_dotdot_state_publish_generated_discover_neighbors_command( false); } /** - * @brief Publishes an incoming/generated Interview command for - * the State cluster. + * @brief Publishes an incoming/generated DeleteAllCredentialsForUser command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/State/GeneratedCommands/Interview + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsForUser * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_state_publish_generated_interview_command( - const dotdot_unid_t unid +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_for_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "State/GeneratedCommands/Interview"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentialsForUser"; std::string payload = - get_json_payload_for_state_interview_command( - ); + get_json_payload_for_user_credential_delete_all_credentials_for_user_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -118318,26 +123999,34 @@ void uic_mqtt_dotdot_state_publish_generated_interview_command( false); } /** - * @brief Publishes an incoming/generated DiscoverSecurity command for - * the State cluster. + * @brief Publishes an incoming/generated DeleteAllCredentialsForUserByType command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/State/GeneratedCommands/DiscoverSecurity + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_state_publish_generated_discover_security_command( - const dotdot_unid_t unid +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_for_user_by_type_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "State/GeneratedCommands/DiscoverSecurity"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType"; std::string payload = - get_json_payload_for_state_discover_security_command( - ); + get_json_payload_for_user_credential_delete_all_credentials_for_user_by_type_command( + fields); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -118346,11 +124035,11 @@ void uic_mqtt_dotdot_state_publish_generated_discover_security_command( false); } /** - * @brief Publishes an incoming/generated Bind command for - * the Binding cluster. + * @brief Publishes an incoming/generated CredentialLearnStartAdd command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/Bind + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStartAdd * * @param unid The UNID of the node that sent us the command. * @@ -118360,19 +124049,19 @@ void uic_mqtt_dotdot_state_publish_generated_discover_security_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_binding_publish_generated_bind_command( +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_start_add_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_binding_command_bind_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Binding/GeneratedCommands/Bind"; + topic += "UserCredential/GeneratedCommands/CredentialLearnStartAdd"; std::string payload = - get_json_payload_for_binding_bind_command( + get_json_payload_for_user_credential_credential_learn_start_add_command( fields); // Publish our command @@ -118382,11 +124071,11 @@ void uic_mqtt_dotdot_binding_publish_generated_bind_command( false); } /** - * @brief Publishes an incoming/generated Unbind command for - * the Binding cluster. + * @brief Publishes an incoming/generated CredentialLearnStartModify command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/Unbind + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStartModify * * @param unid The UNID of the node that sent us the command. * @@ -118396,19 +124085,19 @@ void uic_mqtt_dotdot_binding_publish_generated_bind_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_binding_publish_generated_unbind_command( +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_start_modify_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_binding_command_unbind_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Binding/GeneratedCommands/Unbind"; + topic += "UserCredential/GeneratedCommands/CredentialLearnStartModify"; std::string payload = - get_json_payload_for_binding_unbind_command( + get_json_payload_for_user_credential_credential_learn_start_modify_command( fields); // Publish our command @@ -118418,34 +124107,30 @@ void uic_mqtt_dotdot_binding_publish_generated_unbind_command( false); } /** - * @brief Publishes an incoming/generated BindToProtocolController command for - * the Binding cluster. + * @brief Publishes an incoming/generated CredentialLearnStop command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/BindToProtocolController + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStop * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_binding_publish_generated_bind_to_protocol_controller_command( +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_stop_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_binding_command_bind_to_protocol_controller_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Binding/GeneratedCommands/BindToProtocolController"; + topic += "UserCredential/GeneratedCommands/CredentialLearnStop"; std::string payload = - get_json_payload_for_binding_bind_to_protocol_controller_command( - fields); + get_json_payload_for_user_credential_credential_learn_stop_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), @@ -118454,11 +124139,11 @@ void uic_mqtt_dotdot_binding_publish_generated_bind_to_protocol_controller_comma false); } /** - * @brief Publishes an incoming/generated UnbindFromProtocolController command for - * the Binding cluster. + * @brief Publishes an incoming/generated CredentialAssociation command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/Binding/GeneratedCommands/UnbindFromProtocolController + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialAssociation * * @param unid The UNID of the node that sent us the command. * @@ -118468,19 +124153,19 @@ void uic_mqtt_dotdot_binding_publish_generated_bind_to_protocol_controller_comma * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_binding_publish_generated_unbind_from_protocol_controller_command( +void uic_mqtt_dotdot_user_credential_publish_generated_credential_association_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_binding_command_unbind_from_protocol_controller_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "Binding/GeneratedCommands/UnbindFromProtocolController"; + topic += "UserCredential/GeneratedCommands/CredentialAssociation"; std::string payload = - get_json_payload_for_binding_unbind_from_protocol_controller_command( + get_json_payload_for_user_credential_credential_association_command( fields); // Publish our command @@ -118490,29 +124175,33 @@ void uic_mqtt_dotdot_binding_publish_generated_unbind_from_protocol_controller_c false); } /** - * @brief Publishes an incoming/generated LogEntry command for - * the ApplicationMonitoring cluster. + * @brief Publishes an incoming/generated GetUserChecksum command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/ApplicationMonitoring/GeneratedCommands/LogEntry + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetUserChecksum * * @param unid The UNID of the node that sent us the command. * + * @param endpoint The Endpoint ID of the node that sent us the command. + * * * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_application_monitoring_publish_generated_log_entry_command( +void uic_mqtt_dotdot_user_credential_publish_generated_get_user_checksum_command( const dotdot_unid_t unid, - const uic_mqtt_dotdot_application_monitoring_command_log_entry_fields_t *fields + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields ) { // Create the topic - std::string topic = "ucl/by-unid/" + std::string(unid) + "/"; - topic += "ApplicationMonitoring/GeneratedCommands/LogEntry"; + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/GetUserChecksum"; std::string payload = - get_json_payload_for_application_monitoring_log_entry_command( + get_json_payload_for_user_credential_get_user_checksum_command( fields); // Publish our command @@ -118522,11 +124211,11 @@ void uic_mqtt_dotdot_application_monitoring_publish_generated_log_entry_command( false); } /** - * @brief Publishes an incoming/generated DiscoverParameter command for - * the ConfigurationParameters cluster. + * @brief Publishes an incoming/generated GetCredentialChecksum command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/DiscoverParameter + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetCredentialChecksum * * @param unid The UNID of the node that sent us the command. * @@ -118536,19 +124225,19 @@ void uic_mqtt_dotdot_application_monitoring_publish_generated_log_entry_command( * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_configuration_parameters_publish_generated_discover_parameter_command( +void uic_mqtt_dotdot_user_credential_publish_generated_get_credential_checksum_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_configuration_parameters_command_discover_parameter_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ConfigurationParameters/GeneratedCommands/DiscoverParameter"; + topic += "UserCredential/GeneratedCommands/GetCredentialChecksum"; std::string payload = - get_json_payload_for_configuration_parameters_discover_parameter_command( + get_json_payload_for_user_credential_get_credential_checksum_command( fields); // Publish our command @@ -118558,11 +124247,11 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_discover_paramet false); } /** - * @brief Publishes an incoming/generated DefaultResetAllParameters command for - * the ConfigurationParameters cluster. + * @brief Publishes an incoming/generated GetAllUsersChecksum command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/DefaultResetAllParameters + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetAllUsersChecksum * * @param unid The UNID of the node that sent us the command. * @@ -118570,17 +124259,17 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_discover_paramet * * */ -void uic_mqtt_dotdot_configuration_parameters_publish_generated_default_reset_all_parameters_command( +void uic_mqtt_dotdot_user_credential_publish_generated_get_all_users_checksum_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ConfigurationParameters/GeneratedCommands/DefaultResetAllParameters"; + topic += "UserCredential/GeneratedCommands/GetAllUsersChecksum"; std::string payload = - get_json_payload_for_configuration_parameters_default_reset_all_parameters_command( + get_json_payload_for_user_credential_get_all_users_checksum_command( ); // Publish our command @@ -118590,11 +124279,11 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_default_reset_al false); } /** - * @brief Publishes an incoming/generated SetParameter command for - * the ConfigurationParameters cluster. + * @brief Publishes an incoming/generated SetAdminPINCode command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/SetParameter + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/SetAdminPINCode * * @param unid The UNID of the node that sent us the command. * @@ -118604,19 +124293,19 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_default_reset_al * @param fields Struct pointer with the fields value of the command * */ -void uic_mqtt_dotdot_configuration_parameters_publish_generated_set_parameter_command( +void uic_mqtt_dotdot_user_credential_publish_generated_set_admin_pin_code_command( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_configuration_parameters_command_set_parameter_fields_t *fields + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ConfigurationParameters/GeneratedCommands/SetParameter"; + topic += "UserCredential/GeneratedCommands/SetAdminPINCode"; std::string payload = - get_json_payload_for_configuration_parameters_set_parameter_command( + get_json_payload_for_user_credential_set_admin_pin_code_command( fields); // Publish our command @@ -118626,34 +124315,30 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_set_parameter_co false); } /** - * @brief Publishes an incoming/generated DiscoverParameterRange command for - * the ConfigurationParameters cluster. + * @brief Publishes an incoming/generated DeactivateAdminPINCode command for + * the UserCredential cluster. * * Publication will be made at the following topic - * ucl/by-unid/UNID/epID/ConfigurationParameters/GeneratedCommands/DiscoverParameterRange + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeactivateAdminPINCode * * @param unid The UNID of the node that sent us the command. * * @param endpoint The Endpoint ID of the node that sent us the command. * * - * @param fields Struct pointer with the fields value of the command - * */ -void uic_mqtt_dotdot_configuration_parameters_publish_generated_discover_parameter_range_command( +void uic_mqtt_dotdot_user_credential_publish_generated_deactivate_admin_pin_code_command( const dotdot_unid_t unid, - const dotdot_endpoint_id_t endpoint, - const uic_mqtt_dotdot_configuration_parameters_command_discover_parameter_range_fields_t *fields - + const dotdot_endpoint_id_t endpoint ) { // Create the topic std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + std::to_string(endpoint) + "/"; - topic += "ConfigurationParameters/GeneratedCommands/DiscoverParameterRange"; + topic += "UserCredential/GeneratedCommands/DeactivateAdminPINCode"; std::string payload = - get_json_payload_for_configuration_parameters_discover_parameter_range_command( - fields); + get_json_payload_for_user_credential_deactivate_admin_pin_code_command( + ); // Publish our command uic_mqtt_publish(topic.c_str(), diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp index 28684bad8e..2fc5366892 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt.hpp @@ -346,6 +346,13 @@ sl_status_t uic_mqtt_dotdot_by_group_name_and_location_init(); */ sl_status_t uic_mqtt_dotdot_by_group_configuration_parameters_init(); +/** + * @brief Initialize UserCredential dotdot bygroup command handlers + * + * @returns SL_STATUS_OK on success, error otherwise. + */ +sl_status_t uic_mqtt_dotdot_by_group_user_credential_init(); + /** * @brief Initialize AoXLocator dotdot bygroup command handlers * @@ -4913,6 +4920,407 @@ void uic_mqtt_dotdot_on_configuration_parameters_WriteAttributes( const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/AddUser messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_add_user_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/AddUser + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_add_user( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/ModifyUser messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_modify_user_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/ModifyUser + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_modify_user( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteUser messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_user_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteUser + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_user( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/AddCredential messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_add_credential_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/AddCredential + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_add_credential( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/ModifyCredential messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_modify_credential_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/ModifyCredential + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_modify_credential( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteCredential messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_credential_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteCredential + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_credential( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteAllUsers messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_all_users_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteAllUsers + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_all_users( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteAllCredentials messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentials + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteAllCredentialsByType messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentialsByType + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials_by_type( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteAllCredentialsForUser messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentialsForUser + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeleteAllCredentialsForUserByType messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeleteAllCredentialsForUserByType + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user_by_type( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/CredentialLearnStartAdd messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/CredentialLearnStartAdd + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_credential_learn_start_add( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/CredentialLearnStartModify messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/CredentialLearnStartModify + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_credential_learn_start_modify( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/CredentialLearnStop messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/CredentialLearnStop + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_credential_learn_stop( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/CredentialAssociation messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_credential_association_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/CredentialAssociation + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_credential_association( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/GetUserChecksum messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_get_user_checksum_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/GetUserChecksum + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_get_user_checksum( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/GetCredentialChecksum messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/GetCredentialChecksum + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_get_credential_checksum( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/GetAllUsersChecksum messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/GetAllUsersChecksum + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_get_all_users_checksum( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/SetAdminPINCode messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/SetAdminPINCode + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_set_admin_pin_code( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callbacks pointer for + * by-unid UserCredential/Commands/DeactivateAdminPINCode messages + * + * @returns std::set of callbacks. + */ +std::set &get_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/DeactivateAdminPINCode + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_deactivate_admin_pin_code( + const char *topic, + const char *message, + const size_t message_length); +// clang-format on + +/** + * @brief Retrieves the container with callback pointers for by-unid + * /Commands/WriteAttributes messages + * + * @returns std::set of callbacks. + */ +std::set & get_uic_mqtt_dotdot_user_credential_write_attributes_callback(); + +/** + * @brief MQTT Subscribe handler for incoming publications on: + * ucl/by-unid/+/+/UserCredential/Commands/WriteAttributes + */ +// clang-format off +void uic_mqtt_dotdot_on_user_credential_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length); + + // clang-format on /** @@ -6135,6 +6543,60 @@ const std::vector, std::vector, std::vector>>> UserCredentialSupportedCredentialRules_bitmap_data { +{ {"Single", "bool", "0x2", "1"}, { +} }, +{ {"Dual", "bool", "0x4", "2"}, { +} }, +{ {"Triple", "bool", "0x8", "3"}, { +} } +}; +const dotdot_bitmap UserCredentialSupportedCredentialRules("UserCredentialSupportedCredentialRules", "Unknown UserCredentialSupportedCredentialRules", UserCredentialSupportedCredentialRules_bitmap_data); + +const std::vector, std::vector>>> UserCredentialSupportedCredentialTypes_bitmap_data { +{ {"PINCode", "bool", "0x1", "0"}, { +} }, +{ {"Password", "bool", "0x2", "1"}, { +} }, +{ {"RFIDCode", "bool", "0x4", "2"}, { +} }, +{ {"BLE", "bool", "0x8", "3"}, { +} }, +{ {"NFC", "bool", "0x10", "4"}, { +} }, +{ {"UWB", "bool", "0x20", "5"}, { +} }, +{ {"EyeBiometric", "bool", "0x40", "6"}, { +} }, +{ {"FaceBiometric", "bool", "0x80", "7"}, { +} }, +{ {"FingerBiometric", "bool", "0x100", "8"}, { +} }, +{ {"HandBiometric", "bool", "0x200", "9"}, { +} }, +{ {"UnspecifiedBiometric", "bool", "0x400", "10"}, { +} } +}; +const dotdot_bitmap UserCredentialSupportedCredentialTypes("UserCredentialSupportedCredentialTypes", "Unknown UserCredentialSupportedCredentialTypes", UserCredentialSupportedCredentialTypes_bitmap_data); + +const std::vector, std::vector>>> UserCredentialSupportedUserTypes_bitmap_data { +{ {"GeneralUser", "bool", "0x1", "0"}, { +} }, +{ {"ProgrammingUser", "bool", "0x8", "3"}, { +} }, +{ {"NonAccessUser", "bool", "0x10", "4"}, { +} }, +{ {"DuressUser", "bool", "0x20", "5"}, { +} }, +{ {"DisposableUser", "bool", "0x40", "6"}, { +} }, +{ {"ExpiringUser", "bool", "0x80", "7"}, { +} }, +{ {"RemoteOnlyUser", "bool", "0x200", "9"}, { +} } +}; +const dotdot_bitmap UserCredentialSupportedUserTypes("UserCredentialSupportedUserTypes", "Unknown UserCredentialSupportedUserTypes", UserCredentialSupportedUserTypes_bitmap_data); + const std::vector, std::vector>>> WindowCoveringConfigOrStatus_bitmap_data { { {"Operational", "bool", "0x1", "0"}, { } }, diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp index 90161387ae..56ba8db364 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_attributes.cpp @@ -61125,6 +61125,713 @@ void uic_mqtt_dotdot_configuration_parameters_attribute_configuration_parameters // End of supported cluster. +/////////////////////////////////////////////////////////////////////////////// +// Callback pointers for UserCredential +/////////////////////////////////////////////////////////////////////////////// +static uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback_t uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback_t uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback_t uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback_t uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback_t uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback_t uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback_t uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback = nullptr; +static uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback_t uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback = nullptr; + +/////////////////////////////////////////////////////////////////////////////// +// Attribute update handlers for UserCredential +/////////////////////////////////////////////////////////////////////////////// +static void uic_mqtt_dotdot_on_user_credential_supported_user_unique_identifiers_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + uint16_t supported_user_unique_identifiers = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportedUserUniqueIdentifiers: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + supported_user_unique_identifiers = json_payload.at("value").get(); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + supported_user_unique_identifiers + ); + +} +static void uic_mqtt_dotdot_on_user_credential_supported_credential_rules_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + uint8_t supported_credential_rules = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportedCredentialRules: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + supported_credential_rules = uic_dotdot_mqtt::get_bitmap_decimal_value("value", json_payload, UserCredentialSupportedCredentialRules); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + supported_credential_rules + ); + +} +static void uic_mqtt_dotdot_on_user_credential_supported_credential_types_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + uint16_t supported_credential_types = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportedCredentialTypes: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + supported_credential_types = uic_dotdot_mqtt::get_bitmap_decimal_value("value", json_payload, UserCredentialSupportedCredentialTypes); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + supported_credential_types + ); + +} +static void uic_mqtt_dotdot_on_user_credential_supported_user_types_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + uint16_t supported_user_types = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportedUserTypes: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + supported_user_types = uic_dotdot_mqtt::get_bitmap_decimal_value("value", json_payload, UserCredentialSupportedUserTypes); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + supported_user_types + ); + +} +static void uic_mqtt_dotdot_on_user_credential_support_credential_checksum_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + bool support_credential_checksum = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportCredentialChecksum: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + support_credential_checksum = get_bool_from_json(json_payload, "value"); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + support_credential_checksum + ); + +} +static void uic_mqtt_dotdot_on_user_credential_support_admin_pin_code_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + bool support_admin_pin_code = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportAdminPinCode: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + support_admin_pin_code = get_bool_from_json(json_payload, "value"); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + support_admin_pin_code + ); + +} +static void uic_mqtt_dotdot_on_user_credential_support_admin_pin_code_deactivation_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + bool support_admin_pin_code_deactivation = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SupportAdminPinCodeDeactivation: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + support_admin_pin_code_deactivation = get_bool_from_json(json_payload, "value"); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + support_admin_pin_code_deactivation + ); + +} +static void uic_mqtt_dotdot_on_user_credential_admin_pin_code_attribute_update( + const char *topic, + const char *message, + const size_t message_length) { + if (uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback == nullptr) { + return; + } + + std::string unid; + uint8_t endpoint = 0; // Default value for endpoint-less topics. + if(! uic_dotdot_mqtt::parse_topic(topic,unid,endpoint)) { + sl_log_debug(LOG_TAG, + "Error parsing UNID / Endpoint ID from topic %s. Ignoring", + topic); + return; + } + + std::string last_item; + if (SL_STATUS_OK != uic_dotdot_mqtt::get_topic_last_item(topic,last_item)){ + sl_log_debug(LOG_TAG, + "Error parsing last item from topic %s. Ignoring", + topic); + return; + } + + uic_mqtt_dotdot_attribute_update_type_t update_type; + if (last_item == "Reported") { + update_type = UCL_REPORTED_UPDATED; + } else if (last_item == "Desired") { + update_type = UCL_DESIRED_UPDATED; + } else { + sl_log_debug(LOG_TAG, + "Unknown value type (neither Desired/Reported) for topic %s. Ignoring", + topic); + return; + } + + // Empty message means unretained value. + bool unretained = false; + if (message_length == 0) { + unretained = true; + } + + + const char* admin_pin_code = {}; + + nlohmann::json json_payload; + try { + + if (unretained == false) { + json_payload = nlohmann::json::parse(std::string(message)); + + if (json_payload.find("value") == json_payload.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AdminPinCode: Missing attribute element: 'value'\n"); + return; + } +// Start parsing value + admin_pin_code = json_payload.at("value").get_ptr()->c_str(); + + // End parsing value + } + + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "value", message); + return; + } + + uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback( + static_cast(unid.c_str()), + endpoint, + unretained, + update_type, + admin_pin_code + ); + +} + +/////////////////////////////////////////////////////////////////////////////// +// Attribute init functions for UserCredential +/////////////////////////////////////////////////////////////////////////////// +sl_status_t uic_mqtt_dotdot_user_credential_attributes_init() +{ + std::string base_topic = "ucl/by-unid/+/+/"; + + std::string subscription_topic; + if(uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportedUserUniqueIdentifiers/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_supported_user_unique_identifiers_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportedCredentialRules/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_supported_credential_rules_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportedCredentialTypes/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_supported_credential_types_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportedUserTypes/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_supported_user_types_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportCredentialChecksum/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_support_credential_checksum_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportAdminPinCode/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_support_admin_pin_code_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/SupportAdminPinCodeDeactivation/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_support_admin_pin_code_deactivation_attribute_update); + } + if(uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback) { + subscription_topic = base_topic + "UserCredential/Attributes/AdminPinCode/#"; + uic_mqtt_subscribe(subscription_topic.c_str(), &uic_mqtt_dotdot_on_user_credential_admin_pin_code_attribute_update); + } + + return SL_STATUS_OK; +} + + +/////////////////////////////////////////////////////////////////////////////// +// Callback setters and getters for UserCredential +/////////////////////////////////////////////////////////////////////////////// +void uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_supported_user_unique_identifiers_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_supported_credential_rules_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_supported_credential_types_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback_set(const uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_supported_user_types_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback_set(const uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_support_credential_checksum_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback_set(const uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_support_admin_pin_code_deactivation_callback = callback; +} +void uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback_set(const uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_user_credential_attribute_admin_pin_code_callback = callback; +} + +// End of supported cluster. + /////////////////////////////////////////////////////////////////////////////// // Callback pointers for AoXLocator /////////////////////////////////////////////////////////////////////////////// diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp index 94cfd9d935..8c8ae49e6e 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.cpp @@ -14292,6 +14292,1299 @@ void uic_mqtt_dotdot_parse_configuration_parameters_write_attributes( +} + + +std::string get_json_payload_for_user_credential_add_user_command( + + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum AddUser / UserType + #ifdef ADD_USER_USER_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["UserType"] = + add_user_user_type_get_enum_value_name( + (uint32_t)fields->user_type); + #elif defined(USER_TYPE_ENUM_ENUM_NAME_AVAILABLE) + json_payload["UserType"] = + user_type_enum_get_enum_value_name((uint32_t)fields->user_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["UserType"] = fields->user_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserActiveState"] = nlohmann::json(fields->user_active_state); + command_with_no_fields = false; + // Single Value + // Enum AddUser / CredentialRule + #ifdef ADD_USER_CREDENTIAL_RULE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialRule"] = + add_user_credential_rule_get_enum_value_name( + (uint32_t)fields->credential_rule); + #elif defined(CRED_RULE_ENUM_NAME_AVAILABLE) + json_payload["CredentialRule"] = + cred_rule_get_enum_value_name((uint32_t)fields->credential_rule); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialRule"] = fields->credential_rule; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserName"] = nlohmann::json(fields->user_name); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["ExpiringTimeoutMinutes"] = nlohmann::json(fields->expiring_timeout_minutes); + command_with_no_fields = false; + // Single Value + // Enum AddUser / UserNameEncoding + #ifdef ADD_USER_USER_NAME_ENCODING_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["UserNameEncoding"] = + add_user_user_name_encoding_get_enum_value_name( + (uint32_t)fields->user_name_encoding); + #elif defined(USER_NAME_ENCODING_TYPE_ENUM_NAME_AVAILABLE) + json_payload["UserNameEncoding"] = + user_name_encoding_type_get_enum_value_name((uint32_t)fields->user_name_encoding); + #else + // If there is no name value for the enum, just write it directly. + json_payload["UserNameEncoding"] = fields->user_name_encoding; + #endif + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_add_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + UserTypeEnum &user_type, + + bool &user_active_state, + + CredRule &credential_rule, + + std::string &user_name, + + uint16_t &expiring_timeout_minutes, + + UserNameEncodingType &user_name_encoding + +) { + + uint32_t UserType_enum_val = get_enum_decimal_value("UserType", jsn); + if (UserType_enum_val == std::numeric_limits::max()) { + #ifdef USER_TYPE_ENUM_ENUM_NAME_AVAILABLE + UserType_enum_val = user_type_enum_get_enum_value_number(jsn.at("UserType").get()); + #endif + } + uint32_t CredentialRule_enum_val = get_enum_decimal_value("CredentialRule", jsn); + if (CredentialRule_enum_val == std::numeric_limits::max()) { + #ifdef CRED_RULE_ENUM_NAME_AVAILABLE + CredentialRule_enum_val = cred_rule_get_enum_value_number(jsn.at("CredentialRule").get()); + #endif + } + uint32_t UserNameEncoding_enum_val = get_enum_decimal_value("UserNameEncoding", jsn); + if (UserNameEncoding_enum_val == std::numeric_limits::max()) { + #ifdef USER_NAME_ENCODING_TYPE_ENUM_NAME_AVAILABLE + UserNameEncoding_enum_val = user_name_encoding_type_get_enum_value_number(jsn.at("UserNameEncoding").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("UserType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + user_type = static_cast(UserType_enum_val); + if (jsn.at("UserActiveState").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_active_state = jsn.at("UserActiveState").get< bool >(); + if (jsn.at("CredentialRule").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_rule = static_cast(CredentialRule_enum_val); + if (jsn.at("UserName").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_name = jsn.at("UserName").get(); + if (jsn.at("ExpiringTimeoutMinutes").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + expiring_timeout_minutes = jsn.at("ExpiringTimeoutMinutes").get< uint16_t >(); + if (jsn.at("UserNameEncoding").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + user_name_encoding = static_cast(UserNameEncoding_enum_val); +} + + +std::string get_json_payload_for_user_credential_modify_user_command( + + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum ModifyUser / UserType + #ifdef MODIFY_USER_USER_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["UserType"] = + modify_user_user_type_get_enum_value_name( + (uint32_t)fields->user_type); + #elif defined(USER_TYPE_ENUM_ENUM_NAME_AVAILABLE) + json_payload["UserType"] = + user_type_enum_get_enum_value_name((uint32_t)fields->user_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["UserType"] = fields->user_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserActiveState"] = nlohmann::json(fields->user_active_state); + command_with_no_fields = false; + // Single Value + // Enum ModifyUser / CredentialRule + #ifdef MODIFY_USER_CREDENTIAL_RULE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialRule"] = + modify_user_credential_rule_get_enum_value_name( + (uint32_t)fields->credential_rule); + #elif defined(CRED_RULE_ENUM_NAME_AVAILABLE) + json_payload["CredentialRule"] = + cred_rule_get_enum_value_name((uint32_t)fields->credential_rule); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialRule"] = fields->credential_rule; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserName"] = nlohmann::json(fields->user_name); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["ExpiringTimeoutMinutes"] = nlohmann::json(fields->expiring_timeout_minutes); + command_with_no_fields = false; + // Single Value + // Enum ModifyUser / UserNameEncoding + #ifdef MODIFY_USER_USER_NAME_ENCODING_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["UserNameEncoding"] = + modify_user_user_name_encoding_get_enum_value_name( + (uint32_t)fields->user_name_encoding); + #elif defined(USER_NAME_ENCODING_TYPE_ENUM_NAME_AVAILABLE) + json_payload["UserNameEncoding"] = + user_name_encoding_type_get_enum_value_name((uint32_t)fields->user_name_encoding); + #else + // If there is no name value for the enum, just write it directly. + json_payload["UserNameEncoding"] = fields->user_name_encoding; + #endif + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_modify_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + UserTypeEnum &user_type, + + bool &user_active_state, + + CredRule &credential_rule, + + std::string &user_name, + + uint16_t &expiring_timeout_minutes, + + UserNameEncodingType &user_name_encoding + +) { + + uint32_t UserType_enum_val = get_enum_decimal_value("UserType", jsn); + if (UserType_enum_val == std::numeric_limits::max()) { + #ifdef USER_TYPE_ENUM_ENUM_NAME_AVAILABLE + UserType_enum_val = user_type_enum_get_enum_value_number(jsn.at("UserType").get()); + #endif + } + uint32_t CredentialRule_enum_val = get_enum_decimal_value("CredentialRule", jsn); + if (CredentialRule_enum_val == std::numeric_limits::max()) { + #ifdef CRED_RULE_ENUM_NAME_AVAILABLE + CredentialRule_enum_val = cred_rule_get_enum_value_number(jsn.at("CredentialRule").get()); + #endif + } + uint32_t UserNameEncoding_enum_val = get_enum_decimal_value("UserNameEncoding", jsn); + if (UserNameEncoding_enum_val == std::numeric_limits::max()) { + #ifdef USER_NAME_ENCODING_TYPE_ENUM_NAME_AVAILABLE + UserNameEncoding_enum_val = user_name_encoding_type_get_enum_value_number(jsn.at("UserNameEncoding").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("UserType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + user_type = static_cast(UserType_enum_val); + if (jsn.at("UserActiveState").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_active_state = jsn.at("UserActiveState").get< bool >(); + if (jsn.at("CredentialRule").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_rule = static_cast(CredentialRule_enum_val); + if (jsn.at("UserName").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_name = jsn.at("UserName").get(); + if (jsn.at("ExpiringTimeoutMinutes").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + expiring_timeout_minutes = jsn.at("ExpiringTimeoutMinutes").get< uint16_t >(); + if (jsn.at("UserNameEncoding").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + user_name_encoding = static_cast(UserNameEncoding_enum_val); +} + + +std::string get_json_payload_for_user_credential_delete_user_command( + + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_delete_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid + +) { + + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + } + + +std::string get_json_payload_for_user_credential_add_credential_command( + + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum AddCredential / CredentialType + #ifdef ADD_CREDENTIAL_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + add_credential_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialSlot"] = nlohmann::json(fields->credential_slot); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialData"] = nlohmann::json(fields->credential_data); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_add_credential( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + std::string &credential_data + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); + if (jsn.at("CredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_slot = jsn.at("CredentialSlot").get< uint16_t >(); + if (jsn.at("CredentialData").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_data = jsn.at("CredentialData").get(); + } + + +std::string get_json_payload_for_user_credential_modify_credential_command( + + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum ModifyCredential / CredentialType + #ifdef MODIFY_CREDENTIAL_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + modify_credential_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialSlot"] = nlohmann::json(fields->credential_slot); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialData"] = nlohmann::json(fields->credential_data); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_modify_credential( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + std::string &credential_data + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); + if (jsn.at("CredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_slot = jsn.at("CredentialSlot").get< uint16_t >(); + if (jsn.at("CredentialData").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_data = jsn.at("CredentialData").get(); + } + + +std::string get_json_payload_for_user_credential_delete_credential_command( + + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum DeleteCredential / CredentialType + #ifdef DELETE_CREDENTIAL_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + delete_credential_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialSlot"] = nlohmann::json(fields->credential_slot); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_delete_credential( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); + if (jsn.at("CredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_slot = jsn.at("CredentialSlot").get< uint16_t >(); + } + + +std::string get_json_payload_for_user_credential_delete_all_users_command( + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + + + +std::string get_json_payload_for_user_credential_delete_all_credentials_command( + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + + + +std::string get_json_payload_for_user_credential_delete_all_credentials_by_type_command( + + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Enum DeleteAllCredentialsByType / CredentialType + #ifdef DELETE_ALL_CREDENTIALS_BY_TYPE_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + delete_all_credentials_by_type_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_by_type( + nlohmann::json &jsn, + CredType &credential_type + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); +} + + +std::string get_json_payload_for_user_credential_delete_all_credentials_for_user_command( + + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid + +) { + + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + } + + +std::string get_json_payload_for_user_credential_delete_all_credentials_for_user_by_type_command( + + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum DeleteAllCredentialsForUserByType / CredentialType + #ifdef DELETE_ALL_CREDENTIALS_FOR_USER_BY_TYPE_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + delete_all_credentials_for_user_by_type_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user_by_type( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); +} + + +std::string get_json_payload_for_user_credential_credential_learn_start_add_command( + + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum CredentialLearnStartAdd / CredentialType + #ifdef CREDENTIAL_LEARN_START_ADD_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + credential_learn_start_add_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialSlot"] = nlohmann::json(fields->credential_slot); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialLearnTimeout"] = nlohmann::json(fields->credential_learn_timeout); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_credential_learn_start_add( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + uint8_t &credential_learn_timeout + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); + if (jsn.at("CredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_slot = jsn.at("CredentialSlot").get< uint16_t >(); + if (jsn.at("CredentialLearnTimeout").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_learn_timeout = jsn.at("CredentialLearnTimeout").get< uint8_t >(); + } + + +std::string get_json_payload_for_user_credential_credential_learn_start_modify_command( + + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + command_with_no_fields = false; + // Single Value + // Enum CredentialLearnStartModify / CredentialType + #ifdef CREDENTIAL_LEARN_START_MODIFY_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + credential_learn_start_modify_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialSlot"] = nlohmann::json(fields->credential_slot); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["CredentialLearnTimeout"] = nlohmann::json(fields->credential_learn_timeout); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_credential_learn_start_modify( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + uint8_t &credential_learn_timeout + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); + if (jsn.at("CredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_slot = jsn.at("CredentialSlot").get< uint16_t >(); + if (jsn.at("CredentialLearnTimeout").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + credential_learn_timeout = jsn.at("CredentialLearnTimeout").get< uint8_t >(); + } + + +std::string get_json_payload_for_user_credential_credential_learn_stop_command( + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + + + +std::string get_json_payload_for_user_credential_credential_association_command( + + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Enum CredentialAssociation / CredentialType + #ifdef CREDENTIAL_ASSOCIATION_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + credential_association_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["SourceUserUniqueID"] = nlohmann::json(fields->source_user_uniqueid); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["SourceCredentialSlot"] = nlohmann::json(fields->source_credential_slot); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["DestinationUserUniqueID"] = nlohmann::json(fields->destination_user_uniqueid); + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["DestinationCredentialSlot"] = nlohmann::json(fields->destination_credential_slot); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_credential_association( + nlohmann::json &jsn, + CredType &credential_type, + + uint16_t &source_user_uniqueid, + + uint16_t &source_credential_slot, + + uint16_t &destination_user_uniqueid, + + uint16_t &destination_credential_slot + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); + if (jsn.at("SourceUserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + source_user_uniqueid = jsn.at("SourceUserUniqueID").get< uint16_t >(); + if (jsn.at("SourceCredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + source_credential_slot = jsn.at("SourceCredentialSlot").get< uint16_t >(); + if (jsn.at("DestinationUserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + destination_user_uniqueid = jsn.at("DestinationUserUniqueID").get< uint16_t >(); + if (jsn.at("DestinationCredentialSlot").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + destination_credential_slot = jsn.at("DestinationCredentialSlot").get< uint16_t >(); + } + + +std::string get_json_payload_for_user_credential_get_user_checksum_command( + + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["UserUniqueID"] = nlohmann::json(fields->user_uniqueid); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_get_user_checksum( + nlohmann::json &jsn, + uint16_t &user_uniqueid + +) { + + if (jsn.at("UserUniqueID").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + user_uniqueid = jsn.at("UserUniqueID").get< uint16_t >(); + } + + +std::string get_json_payload_for_user_credential_get_credential_checksum_command( + + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Enum GetCredentialChecksum / CredentialType + #ifdef GET_CREDENTIAL_CHECKSUM_CREDENTIAL_TYPE_ENUM_NAME_AVAILABLE + // Pick up the name from the value. + json_payload["CredentialType"] = + get_credential_checksum_credential_type_get_enum_value_name( + (uint32_t)fields->credential_type); + #elif defined(CRED_TYPE_ENUM_NAME_AVAILABLE) + json_payload["CredentialType"] = + cred_type_get_enum_value_name((uint32_t)fields->credential_type); + #else + // If there is no name value for the enum, just write it directly. + json_payload["CredentialType"] = fields->credential_type; + #endif + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_get_credential_checksum( + nlohmann::json &jsn, + CredType &credential_type + +) { + + uint32_t CredentialType_enum_val = get_enum_decimal_value("CredentialType", jsn); + if (CredentialType_enum_val == std::numeric_limits::max()) { + #ifdef CRED_TYPE_ENUM_NAME_AVAILABLE + CredentialType_enum_val = cred_type_get_enum_value_number(jsn.at("CredentialType").get()); + #endif + } + if (jsn.at("CredentialType").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + credential_type = static_cast(CredentialType_enum_val); +} + + +std::string get_json_payload_for_user_credential_get_all_users_checksum_command( + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + + + +std::string get_json_payload_for_user_credential_set_admin_pin_code_command( + + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + command_with_no_fields = false; + // Single Value + // Non-enum and non-bitmask (struct, string or scalar) + json_payload["PINCode"] = nlohmann::json(fields->pin_code); + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + +void uic_mqtt_dotdot_parse_user_credential_set_admin_pin_code( + nlohmann::json &jsn, + std::string &pin_code + +) { + + if (jsn.at("PINCode").is_null()) { + sl_log_debug(LOG_TAG, "Ignoring JSON Null object"); + return; + } + + pin_code = jsn.at("PINCode").get(); + } + + +std::string get_json_payload_for_user_credential_deactivate_admin_pin_code_command( + +){ + bool command_with_no_fields = true; + + // Create a JSON payload from all the parameters + nlohmann::json json_payload; + + // Get the string + if (command_with_no_fields == true) { + return std::string("{}"); + } + // Payload may contain data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + return json_payload.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); +} + + + + +/** + * @brief JSON parser for ::WriteAttributes command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_write_attributes( + nlohmann::json &jsn, + uic_mqtt_dotdot_user_credential_state_t &new_state, + uic_mqtt_dotdot_user_credential_updated_state_t &new_updated_state +) { + + + } diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp index a7de9f2323..6961442ce5 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_command_helpers.hpp @@ -5902,6 +5902,565 @@ void uic_mqtt_dotdot_parse_configuration_parameters_write_attributes( ); +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential AddUser command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_add_user_command( + + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential AddUser command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_add_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + UserTypeEnum &user_type, + + bool &user_active_state, + + CredRule &credential_rule, + + std::string &user_name, + + uint16_t &expiring_timeout_minutes, + + UserNameEncodingType &user_name_encoding + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential ModifyUser command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_modify_user_command( + + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential ModifyUser command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_modify_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + UserTypeEnum &user_type, + + bool &user_active_state, + + CredRule &credential_rule, + + std::string &user_name, + + uint16_t &expiring_timeout_minutes, + + UserNameEncodingType &user_name_encoding + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteUser command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_user_command( + + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential DeleteUser command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_delete_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential AddCredential command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_add_credential_command( + + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential AddCredential command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_add_credential( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + std::string &credential_data + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential ModifyCredential command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_modify_credential_command( + + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential ModifyCredential command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_modify_credential( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + std::string &credential_data + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteCredential command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_credential_command( + + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential DeleteCredential command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_delete_credential( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteAllUsers command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_all_users_command( + +); + + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteAllCredentials command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_all_credentials_command( + +); + + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteAllCredentialsByType command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_all_credentials_by_type_command( + + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential DeleteAllCredentialsByType command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_by_type( + nlohmann::json &jsn, + CredType &credential_type + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteAllCredentialsForUser command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_all_credentials_for_user_command( + + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential DeleteAllCredentialsForUser command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user( + nlohmann::json &jsn, + uint16_t &user_uniqueid + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeleteAllCredentialsForUserByType command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_delete_all_credentials_for_user_by_type_command( + + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential DeleteAllCredentialsForUserByType command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user_by_type( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential CredentialLearnStartAdd command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_credential_learn_start_add_command( + + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential CredentialLearnStartAdd command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_credential_learn_start_add( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + uint8_t &credential_learn_timeout + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential CredentialLearnStartModify command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_credential_learn_start_modify_command( + + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential CredentialLearnStartModify command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_credential_learn_start_modify( + nlohmann::json &jsn, + uint16_t &user_uniqueid, + + CredType &credential_type, + + uint16_t &credential_slot, + + uint8_t &credential_learn_timeout + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential CredentialLearnStop command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_credential_learn_stop_command( + +); + + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential CredentialAssociation command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_credential_association_command( + + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential CredentialAssociation command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_credential_association( + nlohmann::json &jsn, + CredType &credential_type, + + uint16_t &source_user_uniqueid, + + uint16_t &source_credential_slot, + + uint16_t &destination_user_uniqueid, + + uint16_t &destination_credential_slot + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential GetUserChecksum command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_get_user_checksum_command( + + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential GetUserChecksum command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_get_user_checksum( + nlohmann::json &jsn, + uint16_t &user_uniqueid + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential GetCredentialChecksum command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_get_credential_checksum_command( + + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential GetCredentialChecksum command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_get_credential_checksum( + nlohmann::json &jsn, + CredType &credential_type + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential GetAllUsersChecksum command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_get_all_users_checksum_command( + +); + + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential SetAdminPINCode command + * + * @param fields Struct pointer with the list of fields for the command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_set_admin_pin_code_command( + + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +); + + +/** + * @brief JSON parser for UserCredential SetAdminPINCode command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_set_admin_pin_code( + nlohmann::json &jsn, + std::string &pin_code + +); + + + +/** + * @brief Private helper function that will create a JSON string based on the + * fields of a UserCredential DeactivateAdminPINCode command + * + * @returns std::string that contains JSON payload + */ +std::string get_json_payload_for_user_credential_deactivate_admin_pin_code_command( + +); + + + + +/** + * @brief JSON parser for UserCredential WriteAttributes command arguments. + * + * Parse incoming JSON object to populate command arguments passed in by reference. + */ +void uic_mqtt_dotdot_parse_user_credential_write_attributes( + nlohmann::json &jsn, + uic_mqtt_dotdot_user_credential_state_t &new_state, + uic_mqtt_dotdot_user_credential_updated_state_t &new_updated_state +); + + /** * @brief Private helper function that will create a JSON string based on the * fields of a AoXLocator IQReport command diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp index 2fa8037b75..ae06b561cb 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_generated_commands.cpp @@ -10876,6 +10876,746 @@ void uic_mqtt_dotdot_configuration_parameters_publish_generated_write_attributes false); } +/** + * @brief Publishes an incoming/generated AddUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/AddUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_add_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/AddUser"; + + std::string payload = + get_json_payload_for_user_credential_add_user_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated ModifyUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/ModifyUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_modify_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/ModifyUser"; + + std::string payload = + get_json_payload_for_user_credential_modify_user_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteUser"; + + std::string payload = + get_json_payload_for_user_credential_delete_user_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated AddCredential command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/AddCredential + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_add_credential_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/AddCredential"; + + std::string payload = + get_json_payload_for_user_credential_add_credential_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated ModifyCredential command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/ModifyCredential + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_modify_credential_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/ModifyCredential"; + + std::string payload = + get_json_payload_for_user_credential_modify_credential_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteCredential command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteCredential + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_credential_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteCredential"; + + std::string payload = + get_json_payload_for_user_credential_delete_credential_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteAllUsers command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllUsers + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_users_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllUsers"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_users_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteAllCredentials command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentials + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentials"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteAllCredentialsByType command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsByType + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_by_type_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentialsByType"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_by_type_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteAllCredentialsForUser command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsForUser + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_for_user_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentialsForUser"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_for_user_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeleteAllCredentialsForUserByType command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_delete_all_credentials_for_user_by_type_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeleteAllCredentialsForUserByType"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_for_user_by_type_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated CredentialLearnStartAdd command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStartAdd + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_start_add_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/CredentialLearnStartAdd"; + + std::string payload = + get_json_payload_for_user_credential_credential_learn_start_add_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated CredentialLearnStartModify command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStartModify + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_start_modify_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/CredentialLearnStartModify"; + + std::string payload = + get_json_payload_for_user_credential_credential_learn_start_modify_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated CredentialLearnStop command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialLearnStop + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_learn_stop_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/CredentialLearnStop"; + + std::string payload = + get_json_payload_for_user_credential_credential_learn_stop_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated CredentialAssociation command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/CredentialAssociation + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_credential_association_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/CredentialAssociation"; + + std::string payload = + get_json_payload_for_user_credential_credential_association_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated GetUserChecksum command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetUserChecksum + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_get_user_checksum_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/GetUserChecksum"; + + std::string payload = + get_json_payload_for_user_credential_get_user_checksum_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated GetCredentialChecksum command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetCredentialChecksum + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_get_credential_checksum_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/GetCredentialChecksum"; + + std::string payload = + get_json_payload_for_user_credential_get_credential_checksum_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated GetAllUsersChecksum command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/GetAllUsersChecksum + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_get_all_users_checksum_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/GetAllUsersChecksum"; + + std::string payload = + get_json_payload_for_user_credential_get_all_users_checksum_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated SetAdminPINCode command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/SetAdminPINCode + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_set_admin_pin_code_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/SetAdminPINCode"; + + std::string payload = + get_json_payload_for_user_credential_set_admin_pin_code_command( + fields); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} +/** + * @brief Publishes an incoming/generated DeactivateAdminPINCode command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/DeactivateAdminPINCode + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_generated_deactivate_admin_pin_code_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/DeactivateAdminPINCode"; + + std::string payload = + get_json_payload_for_user_credential_deactivate_admin_pin_code_command( + ); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + + +/** + * @brief Publishes an incoming/generated WriteAttributes command for + * the UserCredential cluster. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/GeneratedCommands/WriteAttributes + * + * @param unid The UNID of the node that sent us the command. + * + * @param endpoint The Endpoint ID of the node that sent us the command. + * + * @param attribute_values Values to assign to the attributes + * @param attribute_list List of attributes that are written + */ +void uic_mqtt_dotdot_user_credential_publish_generated_write_attributes_command( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_user_credential_state_t attribute_values, + uic_mqtt_dotdot_user_credential_updated_state_t attribute_list +){ + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(unid) + "/ep" + + std::to_string(endpoint) + "/"; + topic += "UserCredential/GeneratedCommands/WriteAttributes"; + + nlohmann::json json_object = nlohmann::json::object(); + + + // Payload contains data from end nodes, which we cannot control, thus we handle if there are non-utf8 characters + std::string payload = json_object.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace); + + // Publish our command + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + /** * @brief Publishes an incoming/generated IQReport command for * the AoXLocator cluster. diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp index c84e037273..360dbd6475 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_group_commands.cpp @@ -354,6 +354,29 @@ static uic_mqtt_dotdot_by_group_configuration_parameters_discover_parameter_rang static uic_mqtt_dotdot_by_group_configuration_parameters_write_attributes_callback_t uic_mqtt_dotdot_by_group_configuration_parameters_write_attributes_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_add_user_callback_t uic_mqtt_dotdot_by_group_user_credential_add_user_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_modify_user_callback_t uic_mqtt_dotdot_by_group_user_credential_modify_user_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_user_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_user_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_add_credential_callback_t uic_mqtt_dotdot_by_group_user_credential_add_credential_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback_t uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback_t uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback_t uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback_t uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback_t uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_credential_association_callback_t uic_mqtt_dotdot_by_group_user_credential_credential_association_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback_t uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback_t uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback_t uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback_t uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback_t uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback = nullptr; +static uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback_t uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback = nullptr; + + static uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback_t uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback = nullptr; static uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback_t uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback = nullptr; static uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback_t uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback = nullptr; @@ -1844,6 +1867,135 @@ void uic_mqtt_dotdot_by_group_configuration_parameters_write_attributes_callback +// Callbacks setters + +void uic_mqtt_dotdot_by_group_user_credential_add_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_add_user_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_add_user_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_modify_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_modify_user_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_modify_user_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_user_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_user_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_add_credential_callback_set(const uic_mqtt_dotdot_by_group_user_credential_add_credential_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_add_credential_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback_set(const uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback_set(const uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_credential_association_callback_set(const uic_mqtt_dotdot_by_group_user_credential_credential_association_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_credential_association_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback_set(const uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback_set(const uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback_set(const uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback_set(const uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback = callback; +} + + +void uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback_set(const uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback = callback; +} + +void uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback_set( + const uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback_t callback) +{ + uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback = callback; +} + + + // Callbacks setters void uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback_set(const uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback_t callback) @@ -22953,13 +23105,13 @@ sl_status_t uic_mqtt_dotdot_by_group_configuration_parameters_init() -// Callback function for incoming publications on ucl/by-group/+/AoXLocator/Commands/IQReport -static void uic_mqtt_dotdot_on_by_group_aox_locator_iq_report( +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/AddUser +static void uic_mqtt_dotdot_on_by_group_user_credential_add_user( const char *topic, const char *message, const size_t message_length) { - if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback == nullptr)) { + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_add_user_callback == nullptr)) { return; } if (message_length == 0) { @@ -22976,105 +23128,113 @@ static void uic_mqtt_dotdot_on_by_group_aox_locator_iq_report( // Pass to command-specific callback if set. Otherwise, pass to // group-dispatch callback - if (uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback != nullptr) { + if (uic_mqtt_dotdot_by_group_user_credential_add_user_callback != nullptr) { - uic_mqtt_dotdot_aox_locator_command_iq_report_fields_t fields; - std::string tag_unid; - std::vector samples; - + uic_mqtt_dotdot_user_credential_command_add_user_fields_t fields; + std::string user_name; + nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_iq_report( + uic_mqtt_dotdot_parse_user_credential_add_user( jsn, - tag_unid, - - fields.channel, + fields.user_uniqueid, - fields.rssi, + fields.user_type, - samples, + fields.user_active_state, + + fields.credential_rule, + + user_name, - fields.sequence + fields.expiring_timeout_minutes, + + fields.user_name_encoding ); // Populate list fields from vector or string types - fields.tag_unid = tag_unid.c_str(); + fields.user_name = user_name.c_str(); - fields.samples_count = samples.size(); - fields.samples = samples.data(); - } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "IQReport"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "AddUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddUser", ""); return; } - uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback( + uic_mqtt_dotdot_by_group_user_credential_add_user_callback( group_id, &fields ); - } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_iq_report_callback().empty())) { + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_add_user_callback().empty())) { // group-dispatch callback only called if the command-specific by-unid // callback is set try { nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - if (jsn.find("TagUnid") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: TagUnid\n"); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: UserUniqueID\n"); return; } - if (jsn.find("Channel") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: Channel\n"); + if (jsn.find("UserType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: UserType\n"); return; } - if (jsn.find("RSSI") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: RSSI\n"); + if (jsn.find("UserActiveState") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: UserActiveState\n"); return; } - if (jsn.find("Samples") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: Samples\n"); + if (jsn.find("CredentialRule") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: CredentialRule\n"); return; } - if (jsn.find("Sequence") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: Sequence\n"); + if (jsn.find("UserName") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: UserName\n"); + return; + } + if (jsn.find("ExpiringTimeoutMinutes") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: ExpiringTimeoutMinutes\n"); + return; + } + if (jsn.find("UserNameEncoding") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddUser: Missing command-argument: UserNameEncoding\n"); return; } group_dispatch_callback( group_id, - "AoXLocator", - "IQReport", + "UserCredential", + "AddUser", message, message_length, - uic_mqtt_dotdot_on_aox_locator_iq_report); + uic_mqtt_dotdot_on_user_credential_add_user); } catch (...) { - sl_log_debug(LOG_TAG, "IQReport: Unable to parse JSON payload.\n"); + sl_log_debug(LOG_TAG, "AddUser: Unable to parse JSON payload.\n"); return; } } } -// Callback function for incoming publications on ucl/by-group/+/AoXLocator/Commands/AngleReport -static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_report( +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/ModifyUser +static void uic_mqtt_dotdot_on_by_group_user_credential_modify_user( const char *topic, const char *message, const size_t message_length) { - if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback == nullptr)) { + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_modify_user_callback == nullptr)) { return; } if (message_length == 0) { @@ -23091,11 +23251,11 @@ static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_report( // Pass to command-specific callback if set. Otherwise, pass to // group-dispatch callback - if (uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback != nullptr) { + if (uic_mqtt_dotdot_by_group_user_credential_modify_user_callback != nullptr) { - uic_mqtt_dotdot_aox_locator_command_angle_report_fields_t fields; - std::string tag_unid; + uic_mqtt_dotdot_user_credential_command_modify_user_fields_t fields; + std::string user_name; nlohmann::json jsn; @@ -23103,83 +23263,101 @@ static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_report( jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_angle_report( + uic_mqtt_dotdot_parse_user_credential_modify_user( jsn, - tag_unid, - - fields.direction, + fields.user_uniqueid, - fields.deviation, + fields.user_type, - fields.sequence + fields.user_active_state, + + fields.credential_rule, + + user_name, + + fields.expiring_timeout_minutes, + + fields.user_name_encoding ); // Populate list fields from vector or string types - fields.tag_unid = tag_unid.c_str(); + fields.user_name = user_name.c_str(); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleReport"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "ModifyUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyUser", ""); return; } - uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback( + uic_mqtt_dotdot_by_group_user_credential_modify_user_callback( group_id, &fields ); - } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_angle_report_callback().empty())) { + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_modify_user_callback().empty())) { // group-dispatch callback only called if the command-specific by-unid // callback is set try { nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - if (jsn.find("TagUnid") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: TagUnid\n"); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: UserUniqueID\n"); return; } - if (jsn.find("Direction") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: Direction\n"); + if (jsn.find("UserType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: UserType\n"); return; } - if (jsn.find("Deviation") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: Deviation\n"); + if (jsn.find("UserActiveState") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: UserActiveState\n"); return; } - if (jsn.find("Sequence") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: Sequence\n"); + if (jsn.find("CredentialRule") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: CredentialRule\n"); + return; + } + if (jsn.find("UserName") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: UserName\n"); + return; + } + if (jsn.find("ExpiringTimeoutMinutes") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: ExpiringTimeoutMinutes\n"); + return; + } + if (jsn.find("UserNameEncoding") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyUser: Missing command-argument: UserNameEncoding\n"); return; } group_dispatch_callback( group_id, - "AoXLocator", - "AngleReport", + "UserCredential", + "ModifyUser", message, message_length, - uic_mqtt_dotdot_on_aox_locator_angle_report); + uic_mqtt_dotdot_on_user_credential_modify_user); } catch (...) { - sl_log_debug(LOG_TAG, "AngleReport: Unable to parse JSON payload.\n"); + sl_log_debug(LOG_TAG, "ModifyUser: Unable to parse JSON payload.\n"); return; } } } -// Callback function for incoming publications on ucl/by-group/+/AoXLocator/Commands/AngleCorrection -static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_correction( +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteUser +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_user( const char *topic, const char *message, const size_t message_length) { - if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback == nullptr)) { + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_user_callback == nullptr)) { return; } if (message_length == 0) { @@ -23196,95 +23374,75 @@ static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_correction( // Pass to command-specific callback if set. Otherwise, pass to // group-dispatch callback - if (uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback != nullptr) { + if (uic_mqtt_dotdot_by_group_user_credential_delete_user_callback != nullptr) { - uic_mqtt_dotdot_aox_locator_command_angle_correction_fields_t fields; - std::string tag_unid; - + uic_mqtt_dotdot_user_credential_command_delete_user_fields_t fields; + nlohmann::json jsn; try { jsn = nlohmann::json::parse(std::string(message)); - uic_mqtt_dotdot_parse_aox_locator_angle_correction( + uic_mqtt_dotdot_parse_user_credential_delete_user( jsn, - tag_unid, - - fields.direction, - - fields.deviation, - - fields.sequence + fields.user_uniqueid ); // Populate list fields from vector or string types - fields.tag_unid = tag_unid.c_str(); } catch (const nlohmann::json::parse_error& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleCorrection"); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteUser"); return; } catch (const nlohmann::json::exception& e) { // Catch JSON object field parsing errors - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", e.what()); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteUser", e.what()); return; } catch (const std::exception& e) { - sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", ""); + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteUser", ""); return; } - uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback( + uic_mqtt_dotdot_by_group_user_credential_delete_user_callback( group_id, &fields ); - } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_angle_correction_callback().empty())) { + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_user_callback().empty())) { // group-dispatch callback only called if the command-specific by-unid // callback is set try { nlohmann::json jsn = nlohmann::json::parse(std::string(message)); - if (jsn.find("TagUnid") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: TagUnid\n"); - return; - } - if (jsn.find("Direction") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: Direction\n"); - return; - } - if (jsn.find("Deviation") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: Deviation\n"); - return; - } - if (jsn.find("Sequence") == jsn.end()) { - sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: Sequence\n"); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteUser: Missing command-argument: UserUniqueID\n"); return; } group_dispatch_callback( group_id, - "AoXLocator", - "AngleCorrection", + "UserCredential", + "DeleteUser", message, message_length, - uic_mqtt_dotdot_on_aox_locator_angle_correction); + uic_mqtt_dotdot_on_user_credential_delete_user); } catch (...) { - sl_log_debug(LOG_TAG, "AngleCorrection: Unable to parse JSON payload.\n"); + sl_log_debug(LOG_TAG, "DeleteUser: Unable to parse JSON payload.\n"); return; } } } -static void uic_mqtt_dotdot_on_by_group_aox_locator_WriteAttributes( +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/AddCredential +static void uic_mqtt_dotdot_on_by_group_user_credential_add_credential( const char *topic, const char *message, const size_t message_length) { - - if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_write_attributes_callback == nullptr)) { + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_add_credential_callback == nullptr)) { return; } if (message_length == 0) { @@ -23299,25 +23457,2025 @@ static void uic_mqtt_dotdot_on_by_group_aox_locator_WriteAttributes( return; } - if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_write_attributes_callback().empty())) { - try { - group_dispatch_callback(group_id, - "AoXLocator", - "WriteAttributes", - message, - message_length, - uic_mqtt_dotdot_on_aox_locator_WriteAttributes); - - } catch (...) { - sl_log_debug(LOG_TAG, "AoXLocator: Unable to parse JSON payload.\n"); - return; - } - } else if (uic_mqtt_dotdot_by_group_aox_locator_write_attributes_callback != nullptr) { + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_add_credential_callback != nullptr) { - uic_mqtt_dotdot_aox_locator_state_t new_state = {}; - uic_mqtt_dotdot_aox_locator_updated_state_t new_updated_state = {}; - std::vector azimuth_mask; + uic_mqtt_dotdot_user_credential_command_add_credential_fields_t fields; + std::string credential_data; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_add_credential( + jsn, + fields.user_uniqueid, + + fields.credential_type, + + fields.credential_slot, + + credential_data + ); + + // Populate list fields from vector or string types + fields.credential_data = credential_data.c_str(); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "AddCredential"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddCredential", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "AddCredential", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_add_credential_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_add_credential_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddCredential: Missing command-argument: UserUniqueID\n"); + return; + } + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddCredential: Missing command-argument: CredentialType\n"); + return; + } + if (jsn.find("CredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddCredential: Missing command-argument: CredentialSlot\n"); + return; + } + if (jsn.find("CredentialData") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::AddCredential: Missing command-argument: CredentialData\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "AddCredential", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_add_credential); + + } catch (...) { + sl_log_debug(LOG_TAG, "AddCredential: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/ModifyCredential +static void uic_mqtt_dotdot_on_by_group_user_credential_modify_credential( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t fields; + std::string credential_data; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_modify_credential( + jsn, + fields.user_uniqueid, + + fields.credential_type, + + fields.credential_slot, + + credential_data + ); + + // Populate list fields from vector or string types + fields.credential_data = credential_data.c_str(); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "ModifyCredential"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyCredential", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "ModifyCredential", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_modify_credential_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyCredential: Missing command-argument: UserUniqueID\n"); + return; + } + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyCredential: Missing command-argument: CredentialType\n"); + return; + } + if (jsn.find("CredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyCredential: Missing command-argument: CredentialSlot\n"); + return; + } + if (jsn.find("CredentialData") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::ModifyCredential: Missing command-argument: CredentialData\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "ModifyCredential", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_modify_credential); + + } catch (...) { + sl_log_debug(LOG_TAG, "ModifyCredential: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteCredential +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_credential( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_credential( + jsn, + fields.user_uniqueid, + + fields.credential_type, + + fields.credential_slot + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteCredential"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteCredential", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteCredential", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_credential_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteCredential: Missing command-argument: UserUniqueID\n"); + return; + } + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteCredential: Missing command-argument: CredentialType\n"); + return; + } + if (jsn.find("CredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteCredential: Missing command-argument: CredentialSlot\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "DeleteCredential", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_delete_credential); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeleteCredential: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteAllUsers +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_all_users( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback != nullptr) { + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllUsers"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllUsers", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllUsers", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback( + group_id + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_all_users_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + + group_dispatch_callback( + group_id, + "UserCredential", + "DeleteAllUsers", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_delete_all_users); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeleteAllUsers: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteAllCredentials +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback != nullptr) { + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentials"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentials", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentials", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback( + group_id + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + + group_dispatch_callback( + group_id, + "UserCredential", + "DeleteAllCredentials", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_delete_all_credentials); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeleteAllCredentials: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteAllCredentialsByType +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_by_type( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_by_type( + jsn, + fields.credential_type + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsByType"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsByType", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsByType", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteAllCredentialsByType: Missing command-argument: CredentialType\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "DeleteAllCredentialsByType", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_delete_all_credentials_by_type); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeleteAllCredentialsByType: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteAllCredentialsForUser +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_for_user( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user( + jsn, + fields.user_uniqueid + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsForUser"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUser", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUser", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteAllCredentialsForUser: Missing command-argument: UserUniqueID\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "DeleteAllCredentialsForUser", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeleteAllCredentialsForUser: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeleteAllCredentialsForUserByType +static void uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_for_user_by_type( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_delete_all_credentials_for_user_by_type( + jsn, + fields.user_uniqueid, + + fields.credential_type + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeleteAllCredentialsForUserByType"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUserByType", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeleteAllCredentialsForUserByType", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteAllCredentialsForUserByType: Missing command-argument: UserUniqueID\n"); + return; + } + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::DeleteAllCredentialsForUserByType: Missing command-argument: CredentialType\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "DeleteAllCredentialsForUserByType", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_delete_all_credentials_for_user_by_type); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeleteAllCredentialsForUserByType: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/CredentialLearnStartAdd +static void uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_start_add( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_credential_learn_start_add( + jsn, + fields.user_uniqueid, + + fields.credential_type, + + fields.credential_slot, + + fields.credential_learn_timeout + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStartAdd"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartAdd", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartAdd", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartAdd: Missing command-argument: UserUniqueID\n"); + return; + } + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartAdd: Missing command-argument: CredentialType\n"); + return; + } + if (jsn.find("CredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartAdd: Missing command-argument: CredentialSlot\n"); + return; + } + if (jsn.find("CredentialLearnTimeout") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartAdd: Missing command-argument: CredentialLearnTimeout\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "CredentialLearnStartAdd", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_credential_learn_start_add); + + } catch (...) { + sl_log_debug(LOG_TAG, "CredentialLearnStartAdd: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/CredentialLearnStartModify +static void uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_start_modify( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_credential_learn_start_modify( + jsn, + fields.user_uniqueid, + + fields.credential_type, + + fields.credential_slot, + + fields.credential_learn_timeout + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStartModify"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartModify", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStartModify", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartModify: Missing command-argument: UserUniqueID\n"); + return; + } + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartModify: Missing command-argument: CredentialType\n"); + return; + } + if (jsn.find("CredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartModify: Missing command-argument: CredentialSlot\n"); + return; + } + if (jsn.find("CredentialLearnTimeout") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialLearnStartModify: Missing command-argument: CredentialLearnTimeout\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "CredentialLearnStartModify", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_credential_learn_start_modify); + + } catch (...) { + sl_log_debug(LOG_TAG, "CredentialLearnStartModify: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/CredentialLearnStop +static void uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_stop( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback != nullptr) { + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialLearnStop"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStop", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialLearnStop", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback( + group_id + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + + group_dispatch_callback( + group_id, + "UserCredential", + "CredentialLearnStop", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_credential_learn_stop); + + } catch (...) { + sl_log_debug(LOG_TAG, "CredentialLearnStop: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/CredentialAssociation +static void uic_mqtt_dotdot_on_by_group_user_credential_credential_association( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_credential_association_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_credential_association_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_credential_association_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_credential_association( + jsn, + fields.credential_type, + + fields.source_user_uniqueid, + + fields.source_credential_slot, + + fields.destination_user_uniqueid, + + fields.destination_credential_slot + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "CredentialAssociation"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialAssociation", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "CredentialAssociation", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_credential_association_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_credential_association_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialAssociation: Missing command-argument: CredentialType\n"); + return; + } + if (jsn.find("SourceUserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialAssociation: Missing command-argument: SourceUserUniqueID\n"); + return; + } + if (jsn.find("SourceCredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialAssociation: Missing command-argument: SourceCredentialSlot\n"); + return; + } + if (jsn.find("DestinationUserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialAssociation: Missing command-argument: DestinationUserUniqueID\n"); + return; + } + if (jsn.find("DestinationCredentialSlot") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::CredentialAssociation: Missing command-argument: DestinationCredentialSlot\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "CredentialAssociation", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_credential_association); + + } catch (...) { + sl_log_debug(LOG_TAG, "CredentialAssociation: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/GetUserChecksum +static void uic_mqtt_dotdot_on_by_group_user_credential_get_user_checksum( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_get_user_checksum( + jsn, + fields.user_uniqueid + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetUserChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetUserChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetUserChecksum", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_get_user_checksum_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("UserUniqueID") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::GetUserChecksum: Missing command-argument: UserUniqueID\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "GetUserChecksum", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_get_user_checksum); + + } catch (...) { + sl_log_debug(LOG_TAG, "GetUserChecksum: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/GetCredentialChecksum +static void uic_mqtt_dotdot_on_by_group_user_credential_get_credential_checksum( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t fields; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_get_credential_checksum( + jsn, + fields.credential_type + ); + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetCredentialChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetCredentialChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetCredentialChecksum", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("CredentialType") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::GetCredentialChecksum: Missing command-argument: CredentialType\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "GetCredentialChecksum", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_get_credential_checksum); + + } catch (...) { + sl_log_debug(LOG_TAG, "GetCredentialChecksum: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/GetAllUsersChecksum +static void uic_mqtt_dotdot_on_by_group_user_credential_get_all_users_checksum( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback != nullptr) { + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "GetAllUsersChecksum"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetAllUsersChecksum", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "GetAllUsersChecksum", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback( + group_id + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + + group_dispatch_callback( + group_id, + "UserCredential", + "GetAllUsersChecksum", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_get_all_users_checksum); + + } catch (...) { + sl_log_debug(LOG_TAG, "GetAllUsersChecksum: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/SetAdminPINCode +static void uic_mqtt_dotdot_on_by_group_user_credential_set_admin_pin_code( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback != nullptr) { + + + uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t fields; + std::string pin_code; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_user_credential_set_admin_pin_code( + jsn, + pin_code + ); + + // Populate list fields from vector or string types + fields.pin_code = pin_code.c_str(); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "SetAdminPINCode"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "SetAdminPINCode", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "SetAdminPINCode", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("PINCode") == jsn.end()) { + sl_log_debug(LOG_TAG, "UserCredential::SetAdminPINCode: Missing command-argument: PINCode\n"); + return; + } + + group_dispatch_callback( + group_id, + "UserCredential", + "SetAdminPINCode", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_set_admin_pin_code); + + } catch (...) { + sl_log_debug(LOG_TAG, "SetAdminPINCode: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/UserCredential/Commands/DeactivateAdminPINCode +static void uic_mqtt_dotdot_on_by_group_user_credential_deactivate_admin_pin_code( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback != nullptr) { + + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + + // Populate list fields from vector or string types + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "DeactivateAdminPINCode"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeactivateAdminPINCode", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "DeactivateAdminPINCode", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback( + group_id + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + + group_dispatch_callback( + group_id, + "UserCredential", + "DeactivateAdminPINCode", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_deactivate_admin_pin_code); + + } catch (...) { + sl_log_debug(LOG_TAG, "DeactivateAdminPINCode: Unable to parse JSON payload.\n"); + return; + } + } + +} + +static void uic_mqtt_dotdot_on_by_group_user_credential_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) +{ + + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_user_credential_write_attributes_callback().empty())) { + try { + group_dispatch_callback(group_id, + "UserCredential", + "WriteAttributes", + message, + message_length, + uic_mqtt_dotdot_on_user_credential_WriteAttributes); + + } catch (...) { + sl_log_debug(LOG_TAG, "UserCredential: Unable to parse JSON payload.\n"); + return; + } + } else if (uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback != nullptr) { + + uic_mqtt_dotdot_user_credential_state_t new_state = {}; + uic_mqtt_dotdot_user_credential_updated_state_t new_updated_state = {}; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + uic_mqtt_dotdot_parse_user_credential_write_attributes( + jsn, + new_state, + new_updated_state + ); + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "UserCredential", "WriteAttributes"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "WriteAttributes", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "UserCredential", "WriteAttributes", ""); + return; + } + + uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback( + group_id, + new_state, + new_updated_state + ); + } +} + +sl_status_t uic_mqtt_dotdot_by_group_user_credential_init() +{ + std::string subscription_topic; + const std::string topic_bygroup = TOPIC_BY_GROUP_PREFIX; + if(uic_mqtt_dotdot_by_group_user_credential_write_attributes_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/WriteAttributes"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_WriteAttributes); + } + if (uic_mqtt_dotdot_by_group_user_credential_add_user_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/AddUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_add_user); + } + if (uic_mqtt_dotdot_by_group_user_credential_modify_user_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/ModifyUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_modify_user); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_user_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_user); + } + if (uic_mqtt_dotdot_by_group_user_credential_add_credential_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/AddCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_add_credential); + } + if (uic_mqtt_dotdot_by_group_user_credential_modify_credential_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/ModifyCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_modify_credential); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_credential_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteCredential"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_credential); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_users_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteAllUsers"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_all_users); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteAllCredentials"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_by_type_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteAllCredentialsByType"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_by_type); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteAllCredentialsForUser"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_for_user); + } + if (uic_mqtt_dotdot_by_group_user_credential_delete_all_credentials_for_user_by_type_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeleteAllCredentialsForUserByType"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_for_user_by_type); + } + if (uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_add_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/CredentialLearnStartAdd"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_start_add); + } + if (uic_mqtt_dotdot_by_group_user_credential_credential_learn_start_modify_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/CredentialLearnStartModify"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_start_modify); + } + if (uic_mqtt_dotdot_by_group_user_credential_credential_learn_stop_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/CredentialLearnStop"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_stop); + } + if (uic_mqtt_dotdot_by_group_user_credential_credential_association_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/CredentialAssociation"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_credential_association); + } + if (uic_mqtt_dotdot_by_group_user_credential_get_user_checksum_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/GetUserChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_get_user_checksum); + } + if (uic_mqtt_dotdot_by_group_user_credential_get_credential_checksum_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/GetCredentialChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_get_credential_checksum); + } + if (uic_mqtt_dotdot_by_group_user_credential_get_all_users_checksum_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/GetAllUsersChecksum"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_get_all_users_checksum); + } + if (uic_mqtt_dotdot_by_group_user_credential_set_admin_pin_code_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/SetAdminPINCode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_set_admin_pin_code); + } + if (uic_mqtt_dotdot_by_group_user_credential_deactivate_admin_pin_code_callback) { + subscription_topic = topic_bygroup + "UserCredential/Commands/DeactivateAdminPINCode"; + uic_mqtt_subscribe(subscription_topic.c_str(), uic_mqtt_dotdot_on_by_group_user_credential_deactivate_admin_pin_code); + } + + return SL_STATUS_OK; +} + + + + +// Callback function for incoming publications on ucl/by-group/+/AoXLocator/Commands/IQReport +static void uic_mqtt_dotdot_on_by_group_aox_locator_iq_report( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback != nullptr) { + + + uic_mqtt_dotdot_aox_locator_command_iq_report_fields_t fields; + std::string tag_unid; + std::vector samples; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_aox_locator_iq_report( + jsn, + tag_unid, + + fields.channel, + + fields.rssi, + + samples, + + fields.sequence + ); + + // Populate list fields from vector or string types + fields.tag_unid = tag_unid.c_str(); + + fields.samples_count = samples.size(); + fields.samples = samples.data(); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "IQReport"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "IQReport", ""); + return; + } + + uic_mqtt_dotdot_by_group_aox_locator_iq_report_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_iq_report_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("TagUnid") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: TagUnid\n"); + return; + } + if (jsn.find("Channel") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: Channel\n"); + return; + } + if (jsn.find("RSSI") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: RSSI\n"); + return; + } + if (jsn.find("Samples") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: Samples\n"); + return; + } + if (jsn.find("Sequence") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::IQReport: Missing command-argument: Sequence\n"); + return; + } + + group_dispatch_callback( + group_id, + "AoXLocator", + "IQReport", + message, + message_length, + uic_mqtt_dotdot_on_aox_locator_iq_report); + + } catch (...) { + sl_log_debug(LOG_TAG, "IQReport: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/AoXLocator/Commands/AngleReport +static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_report( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback != nullptr) { + + + uic_mqtt_dotdot_aox_locator_command_angle_report_fields_t fields; + std::string tag_unid; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_aox_locator_angle_report( + jsn, + tag_unid, + + fields.direction, + + fields.deviation, + + fields.sequence + ); + + // Populate list fields from vector or string types + fields.tag_unid = tag_unid.c_str(); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleReport"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleReport", ""); + return; + } + + uic_mqtt_dotdot_by_group_aox_locator_angle_report_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_angle_report_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("TagUnid") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: TagUnid\n"); + return; + } + if (jsn.find("Direction") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: Direction\n"); + return; + } + if (jsn.find("Deviation") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: Deviation\n"); + return; + } + if (jsn.find("Sequence") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleReport: Missing command-argument: Sequence\n"); + return; + } + + group_dispatch_callback( + group_id, + "AoXLocator", + "AngleReport", + message, + message_length, + uic_mqtt_dotdot_on_aox_locator_angle_report); + + } catch (...) { + sl_log_debug(LOG_TAG, "AngleReport: Unable to parse JSON payload.\n"); + return; + } + } + +} + +// Callback function for incoming publications on ucl/by-group/+/AoXLocator/Commands/AngleCorrection +static void uic_mqtt_dotdot_on_by_group_aox_locator_angle_correction( + const char *topic, + const char *message, + const size_t message_length) +{ + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + // Pass to command-specific callback if set. Otherwise, pass to + // group-dispatch callback + if (uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback != nullptr) { + + + uic_mqtt_dotdot_aox_locator_command_angle_correction_fields_t fields; + std::string tag_unid; + + + nlohmann::json jsn; + try { + jsn = nlohmann::json::parse(std::string(message)); + + + uic_mqtt_dotdot_parse_aox_locator_angle_correction( + jsn, + tag_unid, + + fields.direction, + + fields.deviation, + + fields.sequence + ); + + // Populate list fields from vector or string types + fields.tag_unid = tag_unid.c_str(); + + + } catch (const nlohmann::json::parse_error& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_PARSE_FAIL, "AoXLocator", "AngleCorrection"); + return; + } catch (const nlohmann::json::exception& e) { + // Catch JSON object field parsing errors + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", e.what()); + return; + } catch (const std::exception& e) { + sl_log_debug(LOG_TAG, LOG_FMT_JSON_ERROR, "AoXLocator", "AngleCorrection", ""); + return; + } + + uic_mqtt_dotdot_by_group_aox_locator_angle_correction_callback( + group_id, + &fields + ); + } else if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_angle_correction_callback().empty())) { + // group-dispatch callback only called if the command-specific by-unid + // callback is set + try { + nlohmann::json jsn = nlohmann::json::parse(std::string(message)); + if (jsn.find("TagUnid") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: TagUnid\n"); + return; + } + if (jsn.find("Direction") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: Direction\n"); + return; + } + if (jsn.find("Deviation") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: Deviation\n"); + return; + } + if (jsn.find("Sequence") == jsn.end()) { + sl_log_debug(LOG_TAG, "AoXLocator::AngleCorrection: Missing command-argument: Sequence\n"); + return; + } + + group_dispatch_callback( + group_id, + "AoXLocator", + "AngleCorrection", + message, + message_length, + uic_mqtt_dotdot_on_aox_locator_angle_correction); + + } catch (...) { + sl_log_debug(LOG_TAG, "AngleCorrection: Unable to parse JSON payload.\n"); + return; + } + } + +} + +static void uic_mqtt_dotdot_on_by_group_aox_locator_WriteAttributes( + const char *topic, + const char *message, + const size_t message_length) +{ + + if ((group_dispatch_callback == nullptr) && (uic_mqtt_dotdot_by_group_aox_locator_write_attributes_callback == nullptr)) { + return; + } + if (message_length == 0) { + return; + } + + dotdot_group_id_t group_id = 0U; + if(!uic_dotdot_mqtt::parse_topic_group_id(topic,group_id)) { + sl_log_debug(LOG_TAG, + "Failed to parse GroupId from topic %s. Ignoring", + topic); + return; + } + + if ((group_dispatch_callback != nullptr) && (!get_uic_mqtt_dotdot_aox_locator_write_attributes_callback().empty())) { + try { + group_dispatch_callback(group_id, + "AoXLocator", + "WriteAttributes", + message, + message_length, + uic_mqtt_dotdot_on_aox_locator_WriteAttributes); + + } catch (...) { + sl_log_debug(LOG_TAG, "AoXLocator: Unable to parse JSON payload.\n"); + return; + } + } else if (uic_mqtt_dotdot_by_group_aox_locator_write_attributes_callback != nullptr) { + + uic_mqtt_dotdot_aox_locator_state_t new_state = {}; + uic_mqtt_dotdot_aox_locator_updated_state_t new_updated_state = {}; + + std::vector azimuth_mask; std::vector elevation_mask; @@ -24446,6 +26604,28 @@ void uic_mqtt_dotdot_set_group_dispatch_callback(group_dispatch_t callback) uic_mqtt_subscribe("ucl/by-group/+/ConfigurationParameters/Commands/SetParameter", uic_mqtt_dotdot_on_by_group_configuration_parameters_set_parameter); uic_mqtt_subscribe("ucl/by-group/+/ConfigurationParameters/Commands/DiscoverParameterRange", uic_mqtt_dotdot_on_by_group_configuration_parameters_discover_parameter_range); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/WriteAttributes", uic_mqtt_dotdot_on_by_group_user_credential_WriteAttributes); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/AddUser", uic_mqtt_dotdot_on_by_group_user_credential_add_user); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/ModifyUser", uic_mqtt_dotdot_on_by_group_user_credential_modify_user); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteUser", uic_mqtt_dotdot_on_by_group_user_credential_delete_user); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/AddCredential", uic_mqtt_dotdot_on_by_group_user_credential_add_credential); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/ModifyCredential", uic_mqtt_dotdot_on_by_group_user_credential_modify_credential); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteCredential", uic_mqtt_dotdot_on_by_group_user_credential_delete_credential); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteAllUsers", uic_mqtt_dotdot_on_by_group_user_credential_delete_all_users); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteAllCredentials", uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteAllCredentialsByType", uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_by_type); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteAllCredentialsForUser", uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_for_user); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeleteAllCredentialsForUserByType", uic_mqtt_dotdot_on_by_group_user_credential_delete_all_credentials_for_user_by_type); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/CredentialLearnStartAdd", uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_start_add); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/CredentialLearnStartModify", uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_start_modify); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/CredentialLearnStop", uic_mqtt_dotdot_on_by_group_user_credential_credential_learn_stop); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/CredentialAssociation", uic_mqtt_dotdot_on_by_group_user_credential_credential_association); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/GetUserChecksum", uic_mqtt_dotdot_on_by_group_user_credential_get_user_checksum); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/GetCredentialChecksum", uic_mqtt_dotdot_on_by_group_user_credential_get_credential_checksum); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/GetAllUsersChecksum", uic_mqtt_dotdot_on_by_group_user_credential_get_all_users_checksum); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/SetAdminPINCode", uic_mqtt_dotdot_on_by_group_user_credential_set_admin_pin_code); + uic_mqtt_subscribe("ucl/by-group/+/UserCredential/Commands/DeactivateAdminPINCode", uic_mqtt_dotdot_on_by_group_user_credential_deactivate_admin_pin_code); + uic_mqtt_subscribe("ucl/by-group/+/AoXLocator/Commands/WriteAttributes", uic_mqtt_dotdot_on_by_group_aox_locator_WriteAttributes); uic_mqtt_subscribe("ucl/by-group/+/AoXLocator/Commands/IQReport", uic_mqtt_dotdot_on_by_group_aox_locator_iq_report); uic_mqtt_subscribe("ucl/by-group/+/AoXLocator/Commands/AngleReport", uic_mqtt_dotdot_on_by_group_aox_locator_angle_report); diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp index b694096f5d..b89f90602b 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_helpers.cpp @@ -1397,6 +1397,100 @@ uint32_t commissioning_startup_control_get_enum_value_number(const std::string & return std::numeric_limits::max(); } +// Enum to string map for CredRule +const std::map cred_rule_enum_id_to_string_map { + { 1, "Single" }, + { 2, "Dual" }, + { 3, "Triple" }, +}; + +// String to enum map for CredRule +const std::map cred_rule_enum_string_to_id_map { + { "Single", 1 }, + { "Dual", 2 }, + { "Triple", 3 }, +}; + +std::string cred_rule_get_enum_value_name( + uint32_t value) +{ + auto it = cred_rule_enum_id_to_string_map.find(value); + if (it != cred_rule_enum_id_to_string_map.end()){ + return it->second; + } + + // No known name value is set for this field. + // Set it to a string version of the value. + return std::to_string(value); +} + +uint32_t cred_rule_get_enum_value_number(const std::string &str) +{ + auto it = cred_rule_enum_string_to_id_map.find(str); + if (it != cred_rule_enum_string_to_id_map.end()){ + return it->second; + } + + // No known numeric value is set for this string. + // Return UINT32_MAX to indicate an error. + return std::numeric_limits::max(); +} + +// Enum to string map for CredType +const std::map cred_type_enum_id_to_string_map { + { 1, "PINCode" }, + { 2, "Password" }, + { 3, "RFIDCode" }, + { 4, "BLE" }, + { 5, "NFC" }, + { 6, "UWB" }, + { 7, "EyeBiometric" }, + { 8, "FaceBiometric" }, + { 9, "FingerBiometric" }, + { 10, "HandBiometric" }, + { 11, "UnspecifiedBiometric" }, +}; + +// String to enum map for CredType +const std::map cred_type_enum_string_to_id_map { + { "PINCode", 1 }, + { "Password", 2 }, + { "RFIDCode", 3 }, + { "BLE", 4 }, + { "NFC", 5 }, + { "UWB", 6 }, + { "EyeBiometric", 7 }, + { "FaceBiometric", 8 }, + { "FingerBiometric", 9 }, + { "HandBiometric", 10 }, + { "UnspecifiedBiometric", 11 }, +}; + +std::string cred_type_get_enum_value_name( + uint32_t value) +{ + auto it = cred_type_enum_id_to_string_map.find(value); + if (it != cred_type_enum_id_to_string_map.end()){ + return it->second; + } + + // No known name value is set for this field. + // Set it to a string version of the value. + return std::to_string(value); +} + +uint32_t cred_type_get_enum_value_number(const std::string &str) +{ + auto it = cred_type_enum_string_to_id_map.find(str); + if (it != cred_type_enum_string_to_id_map.end()){ + return it->second; + } + + // No known numeric value is set for this string. + // Return UINT32_MAX to indicate an error. + return std::numeric_limits::max(); +} + // Enum to string map for CredentialRuleEnum const std::map credential_rule_enum_enum_id_to_string_map { { 0, "Single" }, @@ -5379,6 +5473,135 @@ uint32_t unify_thermostat_thermostat_mode_get_enum_value_number(const std::strin return std::numeric_limits::max(); } +// Enum to string map for UserModifierType +const std::map user_modifier_type_enum_id_to_string_map { + { 0, "DNE" }, + { 1, "Unknown" }, + { 2, "Z-Wave" }, + { 3, "Locally" }, + { 4, "MobileAppOrOtherIoT" }, +}; + +// String to enum map for UserModifierType +const std::map user_modifier_type_enum_string_to_id_map { + { "DNE", 0 }, + { "Unknown", 1 }, + { "Z-Wave", 2 }, + { "Locally", 3 }, + { "MobileAppOrOtherIoT", 4 }, +}; + +std::string user_modifier_type_get_enum_value_name( + uint32_t value) +{ + auto it = user_modifier_type_enum_id_to_string_map.find(value); + if (it != user_modifier_type_enum_id_to_string_map.end()){ + return it->second; + } + + // No known name value is set for this field. + // Set it to a string version of the value. + return std::to_string(value); +} + +uint32_t user_modifier_type_get_enum_value_number(const std::string &str) +{ + auto it = user_modifier_type_enum_string_to_id_map.find(str); + if (it != user_modifier_type_enum_string_to_id_map.end()){ + return it->second; + } + + // No known numeric value is set for this string. + // Return UINT32_MAX to indicate an error. + return std::numeric_limits::max(); +} + +// Enum to string map for UserNameEncodingType +const std::map user_name_encoding_type_enum_id_to_string_map { + { 0, "ASCII" }, + { 1, "OEMExtendedASCII" }, + { 2, "UTF-16" }, +}; + +// String to enum map for UserNameEncodingType +const std::map user_name_encoding_type_enum_string_to_id_map { + { "ASCII", 0 }, + { "OEMExtendedASCII", 1 }, + { "UTF-16", 2 }, +}; + +std::string user_name_encoding_type_get_enum_value_name( + uint32_t value) +{ + auto it = user_name_encoding_type_enum_id_to_string_map.find(value); + if (it != user_name_encoding_type_enum_id_to_string_map.end()){ + return it->second; + } + + // No known name value is set for this field. + // Set it to a string version of the value. + return std::to_string(value); +} + +uint32_t user_name_encoding_type_get_enum_value_number(const std::string &str) +{ + auto it = user_name_encoding_type_enum_string_to_id_map.find(str); + if (it != user_name_encoding_type_enum_string_to_id_map.end()){ + return it->second; + } + + // No known numeric value is set for this string. + // Return UINT32_MAX to indicate an error. + return std::numeric_limits::max(); +} + +// Enum to string map for UserTypeEnum +const std::map user_type_enum_enum_id_to_string_map { + { 0, "GeneralUser" }, + { 3, "ProgrammingUser" }, + { 4, "NonAccessUser" }, + { 5, "DuressUser" }, + { 6, "DisposableUser" }, + { 7, "ExpiringUser" }, + { 9, "RemoteOnlyUser" }, +}; + +// String to enum map for UserTypeEnum +const std::map user_type_enum_enum_string_to_id_map { + { "GeneralUser", 0 }, + { "ProgrammingUser", 3 }, + { "NonAccessUser", 4 }, + { "DuressUser", 5 }, + { "DisposableUser", 6 }, + { "ExpiringUser", 7 }, + { "RemoteOnlyUser", 9 }, +}; + +std::string user_type_enum_get_enum_value_name( + uint32_t value) +{ + auto it = user_type_enum_enum_id_to_string_map.find(value); + if (it != user_type_enum_enum_id_to_string_map.end()){ + return it->second; + } + + // No known name value is set for this field. + // Set it to a string version of the value. + return std::to_string(value); +} + +uint32_t user_type_enum_get_enum_value_number(const std::string &str) +{ + auto it = user_type_enum_enum_string_to_id_map.find(str); + if (it != user_type_enum_enum_string_to_id_map.end()){ + return it->second; + } + + // No known numeric value is set for this string. + // Return UINT32_MAX to indicate an error. + return std::numeric_limits::max(); +} + // Enum to string map for WindowCoveringWindowCoveringType const std::map window_covering_window_covering_type_enum_id_to_string_map { { 0, "Rollershade" }, @@ -10193,6 +10416,57 @@ std::string get_enum_value_name( #endif } + if (64776 == cluster_id) { + #ifdef USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS_ENUM_NAME_AVAILABLE + if (0 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_user_unique_identifiers instead of this: user_credential_supported_user_unique_identifiers + return user_credential_supported_user_unique_identifiers_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_ENUM_NAME_AVAILABLE + if (1 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_credential_rules instead of this: user_credential_supported_credential_rules + return user_credential_supported_credential_rules_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_ENUM_NAME_AVAILABLE + if (2 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_credential_types instead of this: user_credential_supported_credential_types + return user_credential_supported_credential_types_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORTED_USER_TYPES_ENUM_NAME_AVAILABLE + if (3 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_user_types instead of this: user_credential_supported_user_types + return user_credential_supported_user_types_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM_ENUM_NAME_AVAILABLE + if (4 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupport_credential_checksum instead of this: user_credential_support_credential_checksum + return user_credential_support_credential_checksum_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_ENUM_NAME_AVAILABLE + if (5 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupport_admin_pin_code instead of this: user_credential_support_admin_pin_code + return user_credential_support_admin_pin_code_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION_ENUM_NAME_AVAILABLE + if (6 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupport_admin_pin_code_deactivation instead of this: user_credential_support_admin_pin_code_deactivation + return user_credential_support_admin_pin_code_deactivation_get_enum_value_name(value); + } + #endif + #ifdef USER_CREDENTIAL_ADMIN_PIN_CODE_ENUM_NAME_AVAILABLE + if (7 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialadmin_pin_code instead of this: user_credential_admin_pin_code + return user_credential_admin_pin_code_get_enum_value_name(value); + } + #endif + } + if (64784 == cluster_id) { #ifdef AOX_LOCATOR_REPORTING_MODE_ENUM_NAME_AVAILABLE if (1 == attribute_id) { @@ -14820,6 +15094,57 @@ uint32_t get_enum_name_value( #endif } + if (64776 == cluster_id) { + #ifdef USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS_ENUM_NAME_AVAILABLE + if (0 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_user_unique_identifiers instead of this: user_credential_supported_user_unique_identifiers + return user_credential_supported_user_unique_identifiers_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES_ENUM_NAME_AVAILABLE + if (1 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_credential_rules instead of this: user_credential_supported_credential_rules + return user_credential_supported_credential_rules_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES_ENUM_NAME_AVAILABLE + if (2 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_credential_types instead of this: user_credential_supported_credential_types + return user_credential_supported_credential_types_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORTED_USER_TYPES_ENUM_NAME_AVAILABLE + if (3 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupported_user_types instead of this: user_credential_supported_user_types + return user_credential_supported_user_types_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM_ENUM_NAME_AVAILABLE + if (4 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupport_credential_checksum instead of this: user_credential_support_credential_checksum + return user_credential_support_credential_checksum_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_ENUM_NAME_AVAILABLE + if (5 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupport_admin_pin_code instead of this: user_credential_support_admin_pin_code + return user_credential_support_admin_pin_code_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION_ENUM_NAME_AVAILABLE + if (6 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialsupport_admin_pin_code_deactivation instead of this: user_credential_support_admin_pin_code_deactivation + return user_credential_support_admin_pin_code_deactivation_get_enum_value_number(name); + } + #endif + #ifdef USER_CREDENTIAL_ADMIN_PIN_CODE_ENUM_NAME_AVAILABLE + if (7 == attribute_id) { + // FIXME: Some attributes don't work because multi-upper case names end up like this: user_credentialadmin_pin_code instead of this: user_credential_admin_pin_code + return user_credential_admin_pin_code_get_enum_value_number(name); + } + #endif + } + if (64784 == cluster_id) { #ifdef AOX_LOCATOR_REPORTING_MODE_ENUM_NAME_AVAILABLE if (1 == attribute_id) { @@ -15422,6 +15747,28 @@ uint32_t commissioning_startup_control_get_enum_value_number_c(const char *str) { return commissioning_startup_control_get_enum_value_number(std::string(str)); } +char *cred_rule_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size) +{ + snprintf(result, max_result_size, "%s", cred_rule_get_enum_value_name(value).c_str()); + return result; +} + +uint32_t cred_rule_get_enum_value_number_c(const char *str) +{ + return cred_rule_get_enum_value_number(std::string(str)); +} +char *cred_type_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size) +{ + snprintf(result, max_result_size, "%s", cred_type_get_enum_value_name(value).c_str()); + return result; +} + +uint32_t cred_type_get_enum_value_number_c(const char *str) +{ + return cred_type_get_enum_value_number(std::string(str)); +} char *credential_rule_enum_get_enum_value_name_c( uint32_t value, char *result, size_t max_result_size) { @@ -16434,6 +16781,39 @@ uint32_t unify_thermostat_thermostat_mode_get_enum_value_number_c(const char *st { return unify_thermostat_thermostat_mode_get_enum_value_number(std::string(str)); } +char *user_modifier_type_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size) +{ + snprintf(result, max_result_size, "%s", user_modifier_type_get_enum_value_name(value).c_str()); + return result; +} + +uint32_t user_modifier_type_get_enum_value_number_c(const char *str) +{ + return user_modifier_type_get_enum_value_number(std::string(str)); +} +char *user_name_encoding_type_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size) +{ + snprintf(result, max_result_size, "%s", user_name_encoding_type_get_enum_value_name(value).c_str()); + return result; +} + +uint32_t user_name_encoding_type_get_enum_value_number_c(const char *str) +{ + return user_name_encoding_type_get_enum_value_number(std::string(str)); +} +char *user_type_enum_get_enum_value_name_c( + uint32_t value, char *result, size_t max_result_size) +{ + snprintf(result, max_result_size, "%s", user_type_enum_get_enum_value_name(value).c_str()); + return result; +} + +uint32_t user_type_enum_get_enum_value_number_c(const char *str) +{ + return user_type_enum_get_enum_value_number(std::string(str)); +} char *window_covering_window_covering_type_get_enum_value_name_c( uint32_t value, char *result, size_t max_result_size) { diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp index 5f05c29c2d..0bac1ec2d1 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_send_commands.cpp @@ -13444,6 +13444,1446 @@ void uic_mqtt_dotdot_configuration_parameters_publish_discover_parameter_range_c false); } +/** + * @brief Sends/Publishes a AddUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/AddUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/AddUser"; + + + std::string payload = + get_json_payload_for_user_credential_add_user_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a AddUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/AddUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_add_user_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/AddUser"; + + std::string payload = + get_json_payload_for_user_credential_add_user_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a ModifyUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/ModifyUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/ModifyUser"; + + + std::string payload = + get_json_payload_for_user_credential_modify_user_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a ModifyUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/ModifyUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_modify_user_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/ModifyUser"; + + std::string payload = + get_json_payload_for_user_credential_modify_user_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteUser"; + + + std::string payload = + get_json_payload_for_user_credential_delete_user_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_user_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteUser"; + + std::string payload = + get_json_payload_for_user_credential_delete_user_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a AddCredential command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/AddCredential + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_credential_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/AddCredential"; + + + std::string payload = + get_json_payload_for_user_credential_add_credential_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a AddCredential command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/AddCredential + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_add_credential_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_add_credential_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/AddCredential"; + + std::string payload = + get_json_payload_for_user_credential_add_credential_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a ModifyCredential command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/ModifyCredential + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_credential_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/ModifyCredential"; + + + std::string payload = + get_json_payload_for_user_credential_modify_credential_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a ModifyCredential command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/ModifyCredential + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_modify_credential_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_modify_credential_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/ModifyCredential"; + + std::string payload = + get_json_payload_for_user_credential_modify_credential_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteCredential command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteCredential + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_credential_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteCredential"; + + + std::string payload = + get_json_payload_for_user_credential_delete_credential_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteCredential command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteCredential + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_credential_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_credential_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteCredential"; + + std::string payload = + get_json_payload_for_user_credential_delete_credential_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllUsers command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllUsers + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_users_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteAllUsers"; + + + std::string payload = + get_json_payload_for_user_credential_delete_all_users_command( + ); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllUsers command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllUsers + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_users_command_to_group( + uint16_t destination_group_id +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteAllUsers"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_users_command( + ); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentials command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentials + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteAllCredentials"; + + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_command( + ); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentials command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentials + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_command_to_group( + uint16_t destination_group_id +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteAllCredentials"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_command( + ); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentialsByType command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentialsByType + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_by_type_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteAllCredentialsByType"; + + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_by_type_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentialsByType command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentialsByType + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_by_type_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_by_type_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteAllCredentialsByType"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_by_type_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUser command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentialsForUser + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteAllCredentialsForUser"; + + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_for_user_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUser command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentialsForUser + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteAllCredentialsForUser"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_for_user_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUserByType command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeleteAllCredentialsForUserByType + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_by_type_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeleteAllCredentialsForUserByType"; + + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_for_user_by_type_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeleteAllCredentialsForUserByType command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeleteAllCredentialsForUserByType + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_delete_all_credentials_for_user_by_type_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_delete_all_credentials_for_user_by_type_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeleteAllCredentialsForUserByType"; + + std::string payload = + get_json_payload_for_user_credential_delete_all_credentials_for_user_by_type_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialLearnStartAdd command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialLearnStartAdd + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_add_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/CredentialLearnStartAdd"; + + + std::string payload = + get_json_payload_for_user_credential_credential_learn_start_add_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialLearnStartAdd command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialLearnStartAdd + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_add_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_add_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/CredentialLearnStartAdd"; + + std::string payload = + get_json_payload_for_user_credential_credential_learn_start_add_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialLearnStartModify command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialLearnStartModify + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_modify_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/CredentialLearnStartModify"; + + + std::string payload = + get_json_payload_for_user_credential_credential_learn_start_modify_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialLearnStartModify command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialLearnStartModify + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_start_modify_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_credential_learn_start_modify_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/CredentialLearnStartModify"; + + std::string payload = + get_json_payload_for_user_credential_credential_learn_start_modify_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialLearnStop command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialLearnStop + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_stop_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/CredentialLearnStop"; + + + std::string payload = + get_json_payload_for_user_credential_credential_learn_stop_command( + ); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialLearnStop command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialLearnStop + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_learn_stop_command_to_group( + uint16_t destination_group_id +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/CredentialLearnStop"; + + std::string payload = + get_json_payload_for_user_credential_credential_learn_stop_command( + ); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialAssociation command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/CredentialAssociation + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_association_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/CredentialAssociation"; + + + std::string payload = + get_json_payload_for_user_credential_credential_association_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a CredentialAssociation command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/CredentialAssociation + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_credential_association_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_credential_association_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/CredentialAssociation"; + + std::string payload = + get_json_payload_for_user_credential_credential_association_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetUserChecksum command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/GetUserChecksum + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_user_checksum_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/GetUserChecksum"; + + + std::string payload = + get_json_payload_for_user_credential_get_user_checksum_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetUserChecksum command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/GetUserChecksum + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_user_checksum_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_get_user_checksum_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/GetUserChecksum"; + + std::string payload = + get_json_payload_for_user_credential_get_user_checksum_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetCredentialChecksum command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/GetCredentialChecksum + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_credential_checksum_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/GetCredentialChecksum"; + + + std::string payload = + get_json_payload_for_user_credential_get_credential_checksum_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetCredentialChecksum command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/GetCredentialChecksum + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_credential_checksum_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_get_credential_checksum_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/GetCredentialChecksum"; + + std::string payload = + get_json_payload_for_user_credential_get_credential_checksum_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetAllUsersChecksum command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/GetAllUsersChecksum + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_all_users_checksum_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/GetAllUsersChecksum"; + + + std::string payload = + get_json_payload_for_user_credential_get_all_users_checksum_command( + ); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a GetAllUsersChecksum command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/GetAllUsersChecksum + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_get_all_users_checksum_command_to_group( + uint16_t destination_group_id +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/GetAllUsersChecksum"; + + std::string payload = + get_json_payload_for_user_credential_get_all_users_checksum_command( + ); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a SetAdminPINCode command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/SetAdminPINCode + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_set_admin_pin_code_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/SetAdminPINCode"; + + + std::string payload = + get_json_payload_for_user_credential_set_admin_pin_code_command( + fields); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a SetAdminPINCode command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/SetAdminPINCode + * + * @param destination_group_id The GroupID that should receive the command. + * + * @param fields Struct pointer with the fields value of the command + * + */ +void uic_mqtt_dotdot_user_credential_publish_set_admin_pin_code_command_to_group( + uint16_t destination_group_id, + const uic_mqtt_dotdot_user_credential_command_set_admin_pin_code_fields_t *fields + +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/SetAdminPINCode"; + + std::string payload = + get_json_payload_for_user_credential_set_admin_pin_code_command( + fields); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeactivateAdminPINCode command for + * the UserCredential cluster to a destination. + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/Commands/DeactivateAdminPINCode + * + * @param destination_unid The UNID of the node that should receive the command. + * + * @param destination_endpoint The Endpoint ID of the node that should receive the command. + * + * + */ +void uic_mqtt_dotdot_user_credential_publish_deactivate_admin_pin_code_command( + const dotdot_unid_t destination_unid, + const dotdot_endpoint_id_t destination_endpoint +) { + // Create the topic + std::string topic = "ucl/by-unid/"+ std::string(destination_unid) + "/ep" + + std::to_string(destination_endpoint) + "/"; + topic += "UserCredential/Commands/DeactivateAdminPINCode"; + + + std::string payload = + get_json_payload_for_user_credential_deactivate_admin_pin_code_command( + ); + + sl_log_debug(LOG_TAG, "Sending command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + +/** + * @brief Sends/Publishes a DeactivateAdminPINCode command for + * the UserCredential cluster to a group. + * + * Publication will be made at the following topic + * ucl/by-group/GroupID/UserCredential/Commands/DeactivateAdminPINCode + * + * @param destination_group_id The GroupID that should receive the command. + * + */ +void uic_mqtt_dotdot_user_credential_publish_deactivate_admin_pin_code_command_to_group( + uint16_t destination_group_id +){ + // Create the topic + std::string topic = "ucl/by-group/"+ std::to_string(destination_group_id) + + "/UserCredential/Commands/DeactivateAdminPINCode"; + + std::string payload = + get_json_payload_for_user_credential_deactivate_admin_pin_code_command( + ); + + sl_log_info(LOG_TAG, "Sending group command to %s with payload %s ---", topic.c_str() , payload.c_str()); + + // Publish our command, not retained + uic_mqtt_publish(topic.c_str(), + payload.c_str(), + payload.size(), + false); +} + /** * @brief Sends/Publishes a IQReport command for * the AoXLocator cluster to a destination. diff --git a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp index 18e098f36c..d47afcaa19 100644 --- a/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp +++ b/components/uic_dotdot_mqtt/zap-generated/src/dotdot_mqtt_supported_generated_commands.cpp @@ -2632,6 +2632,109 @@ void uic_mqtt_dotdot_configuration_parameters_publish_supported_generated_comman } +/** + * @brief Sends/Publishes a the SupportedGenerated commands for + * the UserCredential cluster for a UNID/Endpoint + * + * Publication will be made at the following topic + * ucl/by-unid/UNID/epID/UserCredential/SupportedGeneratedCommands + * + * @param unid The UNID of the node on behalf of which the advertisment is made + * + * @param endpoint The Endpoint ID of the node on behalf of which the advertisment is made + * + * @param command_list Struct pointer with the fields value indicating if + * individual commands can be generated. + */ +void uic_mqtt_dotdot_user_credential_publish_supported_generated_commands( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint, + const uic_mqtt_dotdot_user_credential_supported_commands_t *command_list) +{ + std::string topic = "ucl/by-unid/" + std::string(unid); + topic += "/ep"+ std::to_string(endpoint); + topic += "/UserCredential/SupportedGeneratedCommands"; + + // Assemble of vector of strings for the Supported Commands: + std::vector command_vector; + if (command_list->add_user == true) { + command_vector.emplace_back("AddUser"); + } + if (command_list->modify_user == true) { + command_vector.emplace_back("ModifyUser"); + } + if (command_list->delete_user == true) { + command_vector.emplace_back("DeleteUser"); + } + if (command_list->add_credential == true) { + command_vector.emplace_back("AddCredential"); + } + if (command_list->modify_credential == true) { + command_vector.emplace_back("ModifyCredential"); + } + if (command_list->delete_credential == true) { + command_vector.emplace_back("DeleteCredential"); + } + if (command_list->delete_all_users == true) { + command_vector.emplace_back("DeleteAllUsers"); + } + if (command_list->delete_all_credentials == true) { + command_vector.emplace_back("DeleteAllCredentials"); + } + if (command_list->delete_all_credentials_by_type == true) { + command_vector.emplace_back("DeleteAllCredentialsByType"); + } + if (command_list->delete_all_credentials_for_user == true) { + command_vector.emplace_back("DeleteAllCredentialsForUser"); + } + if (command_list->delete_all_credentials_for_user_by_type == true) { + command_vector.emplace_back("DeleteAllCredentialsForUserByType"); + } + if (command_list->credential_learn_start_add == true) { + command_vector.emplace_back("CredentialLearnStartAdd"); + } + if (command_list->credential_learn_start_modify == true) { + command_vector.emplace_back("CredentialLearnStartModify"); + } + if (command_list->credential_learn_stop == true) { + command_vector.emplace_back("CredentialLearnStop"); + } + if (command_list->credential_association == true) { + command_vector.emplace_back("CredentialAssociation"); + } + if (command_list->get_user_checksum == true) { + command_vector.emplace_back("GetUserChecksum"); + } + if (command_list->get_credential_checksum == true) { + command_vector.emplace_back("GetCredentialChecksum"); + } + if (command_list->get_all_users_checksum == true) { + command_vector.emplace_back("GetAllUsersChecksum"); + } + if (command_list->set_admin_pin_code == true) { + command_vector.emplace_back("SetAdminPINCode"); + } + if (command_list->deactivate_admin_pin_code == true) { + command_vector.emplace_back("DeactivateAdminPINCode"); + } + if (command_list->write_attributes == true) { + command_vector.emplace_back("WriteAttributes"); + } + + // JSONify, then Stringify + nlohmann::json json_payload; + json_payload["value"] = command_vector; + std::string string_payload = json_payload.dump(); + + // Publish to MQTT + uic_mqtt_publish(topic.c_str(), + string_payload.c_str(), + string_payload.length(), + true); + +} + + /** * @brief Sends/Publishes a the SupportedGenerated commands for * the AoXLocator cluster for a UNID/Endpoint diff --git a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include index b9482eeb88..4c7a38b1f4 100644 --- a/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include +++ b/components/uic_dotdot_mqtt/zap-generated/test/dotdot_mqtt_test.include @@ -2949,6 +2949,318 @@ static sl_status_t uic_mqtt_dotdot_configuration_parameters_discover_parameter_r return SL_STATUS_OK; } +static unsigned int uic_mqtt_dotdot_user_credential_add_user_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_add_user_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + UserTypeEnum user_type, + + bool user_active_state, + + CredRule credential_rule, + + const char* user_name, + + uint16_t expiring_timeout_minutes, + + UserNameEncodingType user_name_encoding + +) { + uic_mqtt_dotdot_user_credential_add_user_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_modify_user_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_modify_user_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + UserTypeEnum user_type, + + bool user_active_state, + + CredRule credential_rule, + + const char* user_name, + + uint16_t expiring_timeout_minutes, + + UserNameEncodingType user_name_encoding + +) { + uic_mqtt_dotdot_user_credential_modify_user_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_user_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_user_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid + +) { + uic_mqtt_dotdot_user_credential_delete_user_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_add_credential_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_add_credential_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + const char* credential_data + +) { + uic_mqtt_dotdot_user_credential_add_credential_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_modify_credential_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_modify_credential_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + const char* credential_data + +) { + uic_mqtt_dotdot_user_credential_modify_credential_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_credential_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_credential_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot + +) { + uic_mqtt_dotdot_user_credential_delete_credential_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_all_users_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_all_users_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + uic_mqtt_dotdot_user_credential_delete_all_users_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + CredType credential_type + +) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid + +) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + CredType credential_type + +) { + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + uint8_t credential_learn_timeout + +) { + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid, + + CredType credential_type, + + uint16_t credential_slot, + + uint8_t credential_learn_timeout + +) { + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_credential_association_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_credential_association_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + CredType credential_type, + + uint16_t source_user_uniqueid, + + uint16_t source_credential_slot, + + uint16_t destination_user_uniqueid, + + uint16_t destination_credential_slot + +) { + uic_mqtt_dotdot_user_credential_credential_association_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_get_user_checksum_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_get_user_checksum_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + uint16_t user_uniqueid + +) { + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + CredType credential_type + +) { + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type, + const char* pin_code + +) { + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + +static unsigned int uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_count; +static sl_status_t uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_func( + dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint, + uic_mqtt_dotdot_callback_call_type_t callback_type +) { + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_count++; + num_command_callbacks++; + return SL_STATUS_OK; +} + static unsigned int uic_mqtt_dotdot_aox_locator_iq_report_callback_count; static sl_status_t uic_mqtt_dotdot_aox_locator_iq_report_callback_func( dotdot_unid_t unid, @@ -3450,6 +3762,46 @@ static unsigned int set_all_callbacks() num_callbacks++; uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_set(&uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_func); num_callbacks++; + uic_mqtt_dotdot_user_credential_add_user_callback_set(&uic_mqtt_dotdot_user_credential_add_user_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_modify_user_callback_set(&uic_mqtt_dotdot_user_credential_modify_user_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_user_callback_set(&uic_mqtt_dotdot_user_credential_delete_user_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_add_credential_callback_set(&uic_mqtt_dotdot_user_credential_add_credential_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_modify_credential_callback_set(&uic_mqtt_dotdot_user_credential_modify_credential_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_credential_callback_set(&uic_mqtt_dotdot_user_credential_delete_credential_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_all_users_callback_set(&uic_mqtt_dotdot_user_credential_delete_all_users_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set(&uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set(&uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set(&uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set(&uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set(&uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set(&uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set(&uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_credential_association_callback_set(&uic_mqtt_dotdot_user_credential_credential_association_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set(&uic_mqtt_dotdot_user_credential_get_user_checksum_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set(&uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set(&uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set(&uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_func); + num_callbacks++; + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set(&uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_func); + num_callbacks++; uic_mqtt_dotdot_aox_locator_iq_report_callback_set(&uic_mqtt_dotdot_aox_locator_iq_report_callback_func); num_callbacks++; uic_mqtt_dotdot_aox_locator_angle_report_callback_set(&uic_mqtt_dotdot_aox_locator_angle_report_callback_func); @@ -3705,6 +4057,27 @@ static void unset_all_callbacks() uic_mqtt_dotdot_configuration_parameters_set_parameter_callback_clear(); uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_clear(); uic_mqtt_dotdot_clear_configuration_parameters_write_attributes_callbacks(); + uic_mqtt_dotdot_user_credential_add_user_callback_clear(); + uic_mqtt_dotdot_user_credential_modify_user_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_user_callback_clear(); + uic_mqtt_dotdot_user_credential_add_credential_callback_clear(); + uic_mqtt_dotdot_user_credential_modify_credential_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_credential_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_all_users_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_clear(); + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_clear(); + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_clear(); + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_clear(); + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_clear(); + uic_mqtt_dotdot_user_credential_credential_association_callback_clear(); + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_clear(); + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_clear(); + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_clear(); + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_clear(); + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_clear(); + uic_mqtt_dotdot_clear_user_credential_write_attributes_callbacks(); uic_mqtt_dotdot_aox_locator_iq_report_callback_clear(); uic_mqtt_dotdot_aox_locator_angle_report_callback_clear(); uic_mqtt_dotdot_aox_locator_angle_correction_callback_clear(); @@ -3910,6 +4283,26 @@ static void reset_callback_counters() uic_mqtt_dotdot_configuration_parameters_default_reset_all_parameters_callback_count = 0; uic_mqtt_dotdot_configuration_parameters_set_parameter_callback_count = 0; uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_count = 0; + uic_mqtt_dotdot_user_credential_add_user_callback_count = 0; + uic_mqtt_dotdot_user_credential_modify_user_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_user_callback_count = 0; + uic_mqtt_dotdot_user_credential_add_credential_callback_count = 0; + uic_mqtt_dotdot_user_credential_modify_credential_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_credential_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_all_users_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_count = 0; + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_count = 0; + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_count = 0; + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_count = 0; + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_count = 0; + uic_mqtt_dotdot_user_credential_credential_association_callback_count = 0; + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_count = 0; + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_count = 0; + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_count = 0; + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_count = 0; + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_count = 0; uic_mqtt_dotdot_aox_locator_iq_report_callback_count = 0; uic_mqtt_dotdot_aox_locator_angle_report_callback_count = 0; uic_mqtt_dotdot_aox_locator_angle_correction_callback_count = 0; diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam index 2bf45a75f1..68ed25df42 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam +++ b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes.uam @@ -834,6 +834,16 @@ def DOTDOT_ATTRIBUTE_ID_NAME_AND_LOCATION_LOCATION 0xfd060001 // This represents the attributes in the DotDot ConfigurationParameters cluster def DOTDOT_ATTRIBUTE_ID_CONFIGURATION_PARAMETERS_CONFIGURATION_PARAMETERS 0xfd070000 +// This represents the attributes in the DotDot UserCredential cluster +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS 0xfd080000 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES 0xfd080001 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES 0xfd080002 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES 0xfd080003 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM 0xfd080004 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE 0xfd080005 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION 0xfd080006 +def DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE 0xfd080007 + // This represents the attributes in the DotDot AoXLocator cluster def DOTDOT_ATTRIBUTE_ID_AOX_LOCATOR_REPORTING_MODE 0xfd100001 def DOTDOT_ATTRIBUTE_ID_AOX_LOCATOR_POSITION_AND_ORIENTATION_VALID 0xfd100002 diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam index ceb159d2c2..440dddc2ea 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam +++ b/components/unify_dotdot_attribute_store/zap-generated/include/dotdot_attributes_camel_case.uam @@ -834,6 +834,16 @@ def zb_Location 0xfd060001 // This represents short CamelCase labels the attributes in the DotDot ConfigurationParameters cluster def zb_ConfigurationParameters 0xfd070000 +// This represents short CamelCase labels the attributes in the DotDot UserCredential cluster +def zb_SupportedUserUniqueIdentifiers 0xfd080000 +def zb_SupportedCredentialRules 0xfd080001 +def zb_SupportedCredentialTypes 0xfd080002 +def zb_SupportedUserTypes 0xfd080003 +def zb_SupportCredentialChecksum 0xfd080004 +def zb_SupportAdminPinCode 0xfd080005 +def zb_SupportAdminPinCodeDeactivation 0xfd080006 +def zb_AdminPinCode 0xfd080007 + // This represents short CamelCase labels the attributes in the DotDot AoXLocator cluster def zb_ReportingMode 0xfd100001 def zb_PositionAndOrientationValid 0xfd100002 diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h index 85d0e56042..a558a84379 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h +++ b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_attribute_store_helpers.h @@ -75293,6 +75293,885 @@ bool dotdot_is_any_configuration_parameters_writable_attribute_supported( const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); +//////////////////////////////////////////////////////////////////////////////// +// Start of cluster UserCredential +//////////////////////////////////////////////////////////////////////////////// +// UserCredential SupportedUserUniqueIdentifiers +/** + * @brief Verifies if the DotDot UserCredential - SupportedUserUniqueIdentifiers is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportedUserUniqueIdentifiers is supported + * @returns false if SupportedUserUniqueIdentifiers is not supported + */ +bool dotdot_is_supported_user_credential_supported_user_unique_identifiers ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportedUserUniqueIdentifiers attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportedUserUniqueIdentifiers attribute + */ +uint16_t dotdot_get_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportedUserUniqueIdentifiers attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_supported_user_unique_identifiers new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_user_unique_identifiers + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportedUserUniqueIdentifiers + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_user_unique_identifiers_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportedUserUniqueIdentifiers attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_user_unique_identifiers_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportedUserUniqueIdentifiers attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_user_unique_identifiers_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportedUserUniqueIdentifiers attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_user_unique_identifiers_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportedUserUniqueIdentifiers attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential SupportedCredentialRules +/** + * @brief Verifies if the DotDot UserCredential - SupportedCredentialRules is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportedCredentialRules is supported + * @returns false if SupportedCredentialRules is not supported + */ +bool dotdot_is_supported_user_credential_supported_credential_rules ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportedCredentialRules attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportedCredentialRules attribute + */ +uint8_t dotdot_get_user_credential_supported_credential_rules( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportedCredentialRules attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_supported_credential_rules new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_supported_credential_rules( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint8_t new_supported_credential_rules + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportedCredentialRules + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_credential_rules_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportedCredentialRules attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_credential_rules_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportedCredentialRules attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_credential_rules_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportedCredentialRules attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_credential_rules_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportedCredentialRules attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_supported_credential_rules( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential SupportedCredentialTypes +/** + * @brief Verifies if the DotDot UserCredential - SupportedCredentialTypes is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportedCredentialTypes is supported + * @returns false if SupportedCredentialTypes is not supported + */ +bool dotdot_is_supported_user_credential_supported_credential_types ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportedCredentialTypes attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportedCredentialTypes attribute + */ +uint16_t dotdot_get_user_credential_supported_credential_types( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportedCredentialTypes attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_supported_credential_types new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_supported_credential_types( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_credential_types + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportedCredentialTypes + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_credential_types_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportedCredentialTypes attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_credential_types_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportedCredentialTypes attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_credential_types_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportedCredentialTypes attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_credential_types_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportedCredentialTypes attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_supported_credential_types( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential SupportedUserTypes +/** + * @brief Verifies if the DotDot UserCredential - SupportedUserTypes is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportedUserTypes is supported + * @returns false if SupportedUserTypes is not supported + */ +bool dotdot_is_supported_user_credential_supported_user_types ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportedUserTypes attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportedUserTypes attribute + */ +uint16_t dotdot_get_user_credential_supported_user_types( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportedUserTypes attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_supported_user_types new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_supported_user_types( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_user_types + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportedUserTypes + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_user_types_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportedUserTypes attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_supported_user_types_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportedUserTypes attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_user_types_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportedUserTypes attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_supported_user_types_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportedUserTypes attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_supported_user_types( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential SupportCredentialChecksum +/** + * @brief Verifies if the DotDot UserCredential - SupportCredentialChecksum is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportCredentialChecksum is supported + * @returns false if SupportCredentialChecksum is not supported + */ +bool dotdot_is_supported_user_credential_support_credential_checksum ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportCredentialChecksum attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportCredentialChecksum attribute + */ +bool dotdot_get_user_credential_support_credential_checksum( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportCredentialChecksum attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_support_credential_checksum new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_support_credential_checksum( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + bool new_support_credential_checksum + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportCredentialChecksum + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_support_credential_checksum_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportCredentialChecksum attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_support_credential_checksum_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportCredentialChecksum attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_support_credential_checksum_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportCredentialChecksum attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_support_credential_checksum_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportCredentialChecksum attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_support_credential_checksum( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential SupportAdminPinCode +/** + * @brief Verifies if the DotDot UserCredential - SupportAdminPinCode is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportAdminPinCode is supported + * @returns false if SupportAdminPinCode is not supported + */ +bool dotdot_is_supported_user_credential_support_admin_pin_code ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportAdminPinCode attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportAdminPinCode attribute + */ +bool dotdot_get_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportAdminPinCode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_support_admin_pin_code new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + bool new_support_admin_pin_code + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportAdminPinCode + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_support_admin_pin_code_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportAdminPinCode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_support_admin_pin_code_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportAdminPinCode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_support_admin_pin_code_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportAdminPinCode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_support_admin_pin_code_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportAdminPinCode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential SupportAdminPinCodeDeactivation +/** + * @brief Verifies if the DotDot UserCredential - SupportAdminPinCodeDeactivation is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if SupportAdminPinCodeDeactivation is supported + * @returns false if SupportAdminPinCodeDeactivation is not supported + */ +bool dotdot_is_supported_user_credential_support_admin_pin_code_deactivation ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - SupportAdminPinCodeDeactivation attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * + * @returns SupportAdminPinCodeDeactivation attribute + */ +bool dotdot_get_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - SupportAdminPinCodeDeactivation attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_support_admin_pin_code_deactivation new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + bool new_support_admin_pin_code_deactivation + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - SupportAdminPinCodeDeactivation + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_support_admin_pin_code_deactivation_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - SupportAdminPinCodeDeactivation attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_support_admin_pin_code_deactivation_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - SupportAdminPinCodeDeactivation attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_support_admin_pin_code_deactivation_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - SupportAdminPinCodeDeactivation attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_support_admin_pin_code_deactivation_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - SupportAdminPinCodeDeactivation attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); +// UserCredential AdminPinCode +/** + * @brief Verifies if the DotDot UserCredential - AdminPinCode is supported + * under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * + * @returns true if AdminPinCode is supported + * @returns false if AdminPinCode is not supported + */ +bool dotdot_is_supported_user_credential_admin_pin_code ( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Gets the DotDot UserCredential - AdminPinCode attribute value under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to get, + * see \ref attribute_store_get_node_attribute_value + * + * WARNING: This function is not thread safe, if you retrieve a string, read the + * value immediately and cache it yourself before invoking another get function. + * + * + * @returns AdminPinCode attribute + */ +const char* dotdot_get_user_credential_admin_pin_code( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state); + +/** + * @brief Set the DotDot UserCredential - AdminPinCode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @param value_state value state to write for the node, + * see \ref attribute_store_set_node_attribute_value + * + * @param new_admin_pin_code new value to set + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_set_user_credential_admin_pin_code( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + const char* new_admin_pin_code + ); + +/** + * @brief Undefines the Reported value of the the DotDot UserCredential - AdminPinCode + * attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_admin_pin_code_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Undefines the Desired value of the DotDot + * UserCredential - AdminPinCode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_user_credential_admin_pin_code_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the reported value is defined for the DotDot + * UserCredential - AdminPinCode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_admin_pin_code_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if the desired value is defined for the DotDot + * UserCredential - AdminPinCode attribute under a UNID/EndpointID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if defined, false is undefined or non-existent + */ +bool dotdot_user_credential_admin_pin_code_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Creates a DotDot UserCredential - AdminPinCode attribute under a UNID/EndpoinID + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns sl_status_t SL_STATUS_OK on success + */ +sl_status_t dotdot_create_user_credential_admin_pin_code( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if a UNID/Endpoint supports any attribute for the UserCredential + * Cluster + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if at least 1 attribute in the Attribute Store, false otherwise + */ +bool dotdot_is_any_user_credential_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + +/** + * @brief Checks if a UNID/Endpoint supports any writable attribute for the + * UserCredential Cluster + * + * @param unid Node's UNID + * @param endpoint_id Endpoint ID + * @returns true if at least 1 writable attribute in the Attribute Store, false otherwise + */ +bool dotdot_is_any_user_credential_writable_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id); + //////////////////////////////////////////////////////////////////////////////// // Start of cluster AoXLocator //////////////////////////////////////////////////////////////////////////////// diff --git a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h index e710efe70b..3f6bb94ed2 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h +++ b/components/unify_dotdot_attribute_store/zap-generated/include/unify_dotdot_defined_attribute_types.h @@ -769,6 +769,15 @@ DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_NAME_AND_LOCATION_NAME , 0xfd060000) DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_NAME_AND_LOCATION_LOCATION , 0xfd060001) // Attribute Defines for ConfigurationParameters DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_CONFIGURATION_PARAMETERS_CONFIGURATION_PARAMETERS , 0xfd070000) +// Attribute Defines for UserCredential +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS , 0xfd080000) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES , 0xfd080001) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES , 0xfd080002) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES , 0xfd080003) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM , 0xfd080004) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE , 0xfd080005) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION , 0xfd080006) +DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE , 0xfd080007) // Attribute Defines for AoXLocator DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_AOX_LOCATOR_REPORTING_MODE , 0xfd100001) DEFINE_ATTRIBUTE(DOTDOT_ATTRIBUTE_ID_AOX_LOCATOR_POSITION_AND_ORIENTATION_VALID , 0xfd100002) diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp index 4801bc555c..51c736f50d 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_attribute_publisher.cpp @@ -24477,6 +24477,377 @@ static void configuration_parameters_cluster_cluster_revision_callback( } +/** + * @brief Publishes the desired value of an updated attribute store node for + * the UserCredential cluster. + * @param updated_node Updated attribute store node + * @param change Type of change applied + */ +static void user_credential_cluster_publish_desired_value_callback( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + // clang-format on + if (false == is_publish_desired_attribute_values_to_mqtt_enabled()) { + return; + } + if (change == ATTRIBUTE_DELETED || change == ATTRIBUTE_CREATED) { + return; + } + // Scene exception: check that the attribute is not under the Scene Table extension, which is a config and not the node's state. + if (ATTRIBUTE_STORE_INVALID_NODE + != attribute_store_get_first_parent_with_type( + updated_node, + DOTDOT_ATTRIBUTE_ID_SCENES_SCENE_TABLE)) { + return; + } + + // Get the UNID and EndPoint, and prepare the basic topic + char unid[MAXIMUM_UNID_SIZE] = {}; + // clang-format off + // clang-format on + dotdot_endpoint_id_t endpoint_id = 0; + if (SL_STATUS_OK + != unify_dotdot_attributes_get_unid_endpoint()(updated_node, + unid, + &endpoint_id)) { + return; + } + // clang-format off + // clang-format on + + std::string base_topic = "ucl/by-unid/" + std::string(unid); + // clang-format off + base_topic += "/ep" + std::to_string(endpoint_id); + // clang-format on + + attribute_store_type_t type = attribute_store_get_node_type(updated_node); + if (type == ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE) { + sl_log_debug(LOG_TAG, + "Warning: Invalid type for Attribute ID %d, " + "this should not happen.", + updated_node); + return; + } + + // If the value got updated but both Reported and Desired undefined, we skip publication + if (false == attribute_store_is_reported_defined(updated_node) + && false == attribute_store_is_desired_defined(updated_node)) { + sl_log_debug(LOG_TAG, + "Reported/Desired values are undefined. " + "Skipping publication"); + return; + } + + // clang-format off + try { + attribute_store::attribute attr(updated_node); + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS) { + uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES) { + uic_mqtt_dotdot_user_credential_supported_credential_rules_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES) { + uic_mqtt_dotdot_user_credential_supported_credential_types_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES) { + uic_mqtt_dotdot_user_credential_supported_user_types_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM) { + uic_mqtt_dotdot_user_credential_support_credential_checksum_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE) { + uic_mqtt_dotdot_user_credential_support_admin_pin_code_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION) { + uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_publish( + base_topic.c_str(), + static_cast(attr.desired_or_reported()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE) { + std::vector str_desired = attr.desired_or_reported>(); + uic_mqtt_dotdot_user_credential_admin_pin_code_publish( + base_topic.c_str(), + static_cast(str_desired.data()), + UCL_MQTT_PUBLISH_TYPE_DESIRED); + return; + } + } catch (std::exception &ex) { + sl_log_warning(LOG_TAG, "Failed to publish the Desired attribute value: %s", ex.what()); + } +} + +/** + * @brief Publishes the reported value of an updated attribute store node for + * the UserCredential cluster. + * @param updated_node Updated attribute store node + * @param change Type of change applied + */ +static void user_credential_cluster_publish_reported_value_callback( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + // clang-format on + if (false == is_publish_reported_attribute_values_to_mqtt_enabled()) { + return; + } + if (change == ATTRIBUTE_CREATED) { + return; + } + // Scene exception: check that the attribute is not under the Scene Table extension, which is a config and not the node's state. + if (ATTRIBUTE_STORE_INVALID_NODE + != attribute_store_get_first_parent_with_type( + updated_node, + DOTDOT_ATTRIBUTE_ID_SCENES_SCENE_TABLE)) { + return; + } + + // Get the UNID and EndPoint, and prepare the basic topic + char unid[MAXIMUM_UNID_SIZE] = {}; + // clang-format off + // clang-format on + dotdot_endpoint_id_t endpoint_id = 0; + if (SL_STATUS_OK + != unify_dotdot_attributes_get_unid_endpoint()(updated_node, + unid, + &endpoint_id)) { + return; + } + // clang-format off + // clang-format on + + std::string base_topic = "ucl/by-unid/" + std::string(unid); + // clang-format off + base_topic += "/ep" + std::to_string(endpoint_id); + // clang-format on + + attribute_store_type_t type = attribute_store_get_node_type(updated_node); + if (type == ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE) { + sl_log_debug(LOG_TAG, + "Warning: Invalid type for Attribute ID %d, " + "this should not happen.", + updated_node); + return; + } + + // Deletion case: + if (change == ATTRIBUTE_DELETED) { + // clang-format off + switch(type) { + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportedUserUniqueIdentifiers under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportedCredentialRules under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_supported_credential_rules_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportedCredentialTypes under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_supported_credential_types_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportedUserTypes under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_supported_user_types_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportCredentialChecksum under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_support_credential_checksum_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportAdminPinCode under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_support_admin_pin_code_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::SupportAdminPinCodeDeactivation under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + case DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE: + // clang-format on + sl_log_debug(LOG_TAG, + "Unretaining UserCredential::AdminPinCode under topic %s", + base_topic.c_str()); + // clang-format off + uic_mqtt_dotdot_user_credential_admin_pin_code_unretain(base_topic.c_str(), UCL_MQTT_PUBLISH_TYPE_ALL); + break; + default: + break; + } + // clang-format on + return; + } + + // If the value got updated but undefined, we skip publication + if (false == attribute_store_is_reported_defined(updated_node)) { + sl_log_debug(LOG_TAG, "Reported value is undefined. Skipping publication"); + return; + } + + // Else we assume update case: + // clang-format off + try { + attribute_store::attribute attr(updated_node); + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS) { + uic_mqtt_dotdot_user_credential_supported_user_unique_identifiers_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES) { + uic_mqtt_dotdot_user_credential_supported_credential_rules_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES) { + uic_mqtt_dotdot_user_credential_supported_credential_types_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES) { + uic_mqtt_dotdot_user_credential_supported_user_types_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM) { + uic_mqtt_dotdot_user_credential_support_credential_checksum_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE) { + uic_mqtt_dotdot_user_credential_support_admin_pin_code_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION) { + uic_mqtt_dotdot_user_credential_support_admin_pin_code_deactivation_publish( + base_topic.c_str(), + static_cast(attr.reported()), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + if (type == DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE) { + std::vector str_desired = attr.reported>(); + uic_mqtt_dotdot_user_credential_admin_pin_code_publish( + base_topic.c_str(), + static_cast( str_desired.data() ), + (attr.desired_exists() && !attribute_store_is_value_matched(updated_node)) ? UCL_MQTT_PUBLISH_TYPE_REPORTED : UCL_MQTT_PUBLISH_TYPE_ALL); + return; + } + } catch (std::exception &ex) { + sl_log_warning(LOG_TAG, "Failed to publish the Reported attribute value: %s", ex.what()); + } +} + +static void user_credential_cluster_cluster_revision_callback( + attribute_store_node_t updated_node, attribute_store_change_t change) +{ + // clang-format on + if (false == is_publish_reported_attribute_values_to_mqtt_enabled()) { + return; + } + + // Get the UNID and EndPoint, and prepare the basic topic + char unid[MAXIMUM_UNID_SIZE] = {}; + dotdot_endpoint_id_t endpoint_id = 0; + // clang-format off + // clang-format on + if (SL_STATUS_OK + != unify_dotdot_attributes_get_unid_endpoint()(updated_node, + unid, + &endpoint_id)) { + return; + } + // clang-format off + // clang-format on + + std::string base_topic = "ucl/by-unid/" + std::string(unid); + // clang-format off + base_topic += "/ep" + std::to_string(endpoint_id); + + if ((change == ATTRIBUTE_CREATED) || (change == ATTRIBUTE_UPDATED)) { + // On attribute creation, make sure to publish the attribute revision for the first time + std::string cluster_revision_topic = base_topic + "/UserCredential/Attributes/ClusterRevision"; + if (uic_mqtt_count_topics(cluster_revision_topic.c_str()) == 0) { + uic_mqtt_dotdot_user_credential_publish_cluster_revision(base_topic.c_str(), 1); + } + } + + if (change == ATTRIBUTE_DELETED) { + // Check if we just erased the last attribute under a cluster, if yes, unretain + // the Cluster revision too. + if (false == dotdot_is_any_user_credential_attribute_supported(unid, endpoint_id)) { + base_topic += "/UserCredential"; + sl_log_debug(LOG_TAG, "No more attributes supported for UserCredential cluster for UNID %s Endpoint %d. Unretaining leftover topics at %s",unid, endpoint_id, base_topic.c_str()); + uic_mqtt_unretain(base_topic.c_str()); + } + } +} + + /** * @brief Publishes the desired value of an updated attribute store node for * the AoXLocator cluster. @@ -36511,6 +36882,118 @@ sl_status_t unify_dotdot_attribute_store_attribute_publisher_init() configuration_parameters_cluster_cluster_revision_callback, DOTDOT_ATTRIBUTE_ID_CONFIGURATION_PARAMETERS_CONFIGURATION_PARAMETERS); //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + //Desired attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_desired_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE, + DESIRED_ATTRIBUTE); + //Reported attribute state + attribute_store_register_callback_by_type_and_state( + user_credential_cluster_publish_reported_value_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE, + REPORTED_ATTRIBUTE); + //registering a callback when an attribute is created for publishing cluster revision + attribute_store_register_callback_by_type( + user_credential_cluster_cluster_revision_callback, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + //Desired attribute state attribute_store_register_callback_by_type_and_state( aox_locator_cluster_publish_desired_value_callback, DOTDOT_ATTRIBUTE_ID_AOX_LOCATOR_REPORTING_MODE, diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c index 3ff0dbe555..94e0617ef5 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_force_read_attributes_command_callbacks.c @@ -4325,6 +4325,71 @@ static sl_status_t uic_mqtt_dotdot_configuration_parameters_force_read_attribute return SL_STATUS_OK; } //////////////////////////////////////////////////////////////////////////////// +// Start of cluster UserCredential +//////////////////////////////////////////////////////////////////////////////// +static sl_status_t uic_mqtt_dotdot_user_credential_force_read_attributes_callback ( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_user_credential_updated_state_t attribute_list) { + + if (false == is_force_read_attributes_enabled()){ + return SL_STATUS_FAIL; + } + + if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) { + if (is_automatic_deduction_of_supported_commands_enabled()) { + return dotdot_is_any_user_credential_attribute_supported(unid, endpoint_id) ? + SL_STATUS_OK : SL_STATUS_FAIL; + } else { + return SL_STATUS_FAIL; + } + } + + // Go and undefine everything that needs to be read again: + if (true == attribute_list.supported_user_unique_identifiers) { + if (SL_STATUS_OK == dotdot_user_credential_supported_user_unique_identifiers_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportedUserUniqueIdentifiers under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.supported_credential_rules) { + if (SL_STATUS_OK == dotdot_user_credential_supported_credential_rules_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportedCredentialRules under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.supported_credential_types) { + if (SL_STATUS_OK == dotdot_user_credential_supported_credential_types_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportedCredentialTypes under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.supported_user_types) { + if (SL_STATUS_OK == dotdot_user_credential_supported_user_types_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportedUserTypes under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.support_credential_checksum) { + if (SL_STATUS_OK == dotdot_user_credential_support_credential_checksum_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportCredentialChecksum under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.support_admin_pin_code) { + if (SL_STATUS_OK == dotdot_user_credential_support_admin_pin_code_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportAdminPinCode under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.support_admin_pin_code_deactivation) { + if (SL_STATUS_OK == dotdot_user_credential_support_admin_pin_code_deactivation_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::SupportAdminPinCodeDeactivation under %s - Endpoint %d", unid, endpoint_id); + } + } + if (true == attribute_list.admin_pin_code) { + if (SL_STATUS_OK == dotdot_user_credential_admin_pin_code_undefine_reported(unid, endpoint_id)) { + sl_log_debug(LOG_TAG, "Undefined Reported value of UserCredential::AdminPinCode under %s - Endpoint %d", unid, endpoint_id); + } + } + return SL_STATUS_OK; +} +//////////////////////////////////////////////////////////////////////////////// // Start of cluster AoXLocator //////////////////////////////////////////////////////////////////////////////// static sl_status_t uic_mqtt_dotdot_aox_locator_force_read_attributes_callback ( @@ -4802,6 +4867,8 @@ sl_status_t uic_mqtt_dotdot_set_configuration_parameters_force_read_attributes_callback(&uic_mqtt_dotdot_configuration_parameters_force_read_attributes_callback); + uic_mqtt_dotdot_set_user_credential_force_read_attributes_callback(&uic_mqtt_dotdot_user_credential_force_read_attributes_callback); + uic_mqtt_dotdot_set_aox_locator_force_read_attributes_callback(&uic_mqtt_dotdot_aox_locator_force_read_attributes_callback); uic_mqtt_dotdot_set_aox_position_estimation_force_read_attributes_callback(&uic_mqtt_dotdot_aox_position_estimation_force_read_attributes_callback); diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp index 0b8be51f79..395d8977fc 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_helpers.cpp @@ -81048,6 +81048,938 @@ bool dotdot_is_any_configuration_parameters_writable_attribute_supported( const dotdot_endpoint_id_t endpoint_id) { + return false; +} +//////////////////////////////////////////////////////////////////////////////// +// Start of cluster UserCredential +//////////////////////////////////////////////////////////////////////////////// +bool dotdot_is_supported_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + return attribute_store_node_exists(node); +} + +uint16_t dotdot_get_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + + uint16_t result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_user_unique_identifiers + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_supported_user_unique_identifiers, + sizeof(uint16_t)); + } + +sl_status_t dotdot_user_credential_supported_user_unique_identifiers_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_supported_user_unique_identifiers_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_supported_user_unique_identifiers_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_supported_user_unique_identifiers_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_supported_user_unique_identifiers( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_supported_credential_rules( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + return attribute_store_node_exists(node); +} + +uint8_t dotdot_get_user_credential_supported_credential_rules( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + + uint8_t result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_supported_credential_rules( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint8_t new_supported_credential_rules + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_supported_credential_rules, + sizeof(uint8_t)); + } + +sl_status_t dotdot_user_credential_supported_credential_rules_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_supported_credential_rules_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_supported_credential_rules_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_supported_credential_rules_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_supported_credential_rules( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_supported_credential_types( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + return attribute_store_node_exists(node); +} + +uint16_t dotdot_get_user_credential_supported_credential_types( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + + uint16_t result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_supported_credential_types( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_credential_types + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_supported_credential_types, + sizeof(uint16_t)); + } + +sl_status_t dotdot_user_credential_supported_credential_types_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_supported_credential_types_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_supported_credential_types_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_supported_credential_types_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_supported_credential_types( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_supported_user_types( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + return attribute_store_node_exists(node); +} + +uint16_t dotdot_get_user_credential_supported_user_types( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + + uint16_t result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_supported_user_types( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + uint16_t new_supported_user_types + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_supported_user_types, + sizeof(uint16_t)); + } + +sl_status_t dotdot_user_credential_supported_user_types_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_supported_user_types_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_supported_user_types_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_supported_user_types_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_supported_user_types( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_support_credential_checksum( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + return attribute_store_node_exists(node); +} + +bool dotdot_get_user_credential_support_credential_checksum( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + + bool result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_support_credential_checksum( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + bool new_support_credential_checksum + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_support_credential_checksum, + sizeof(bool)); + } + +sl_status_t dotdot_user_credential_support_credential_checksum_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_support_credential_checksum_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_support_credential_checksum_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_support_credential_checksum_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_support_credential_checksum( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + return attribute_store_node_exists(node); +} + +bool dotdot_get_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + + bool result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + bool new_support_admin_pin_code + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_support_admin_pin_code, + sizeof(bool)); + } + +sl_status_t dotdot_user_credential_support_admin_pin_code_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_support_admin_pin_code_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_support_admin_pin_code_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_support_admin_pin_code_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_support_admin_pin_code( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + return attribute_store_node_exists(node); +} + +bool dotdot_get_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + + bool result = {}; + attribute_store_read_value(node, + value_state, + (uint8_t *)&result, + sizeof(result)); + return result; +} + +sl_status_t dotdot_set_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + bool new_support_admin_pin_code_deactivation + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + + return attribute_store_set_node_attribute_value(node, + value_state, + (uint8_t *)&new_support_admin_pin_code_deactivation, + sizeof(bool)); + } + +sl_status_t dotdot_user_credential_support_admin_pin_code_deactivation_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_support_admin_pin_code_deactivation_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_support_admin_pin_code_deactivation_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_support_admin_pin_code_deactivation_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_support_admin_pin_code_deactivation( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} +bool dotdot_is_supported_user_credential_admin_pin_code( + const dotdot_unid_t unid, const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + return attribute_store_node_exists(node); +} + +const char* dotdot_get_user_credential_admin_pin_code( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + + if (REPORTED_ATTRIBUTE == value_state) { + attribute_store_get_reported_string(node, received_string, ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH); + } else { + attribute_store_get_desired_string(node, received_string, ATTRIBUTE_STORE_MAXIMUM_VALUE_LENGTH); + } + return received_string; +} + +sl_status_t dotdot_set_user_credential_admin_pin_code( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + attribute_store_node_value_state_t value_state, + const char* new_admin_pin_code + ) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + + if (REPORTED_ATTRIBUTE == value_state){ + return attribute_store_set_reported_string(node, new_admin_pin_code); + } else { + return attribute_store_set_desired_string(node, new_admin_pin_code); + } +} + +sl_status_t dotdot_user_credential_admin_pin_code_undefine_reported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + attribute_store_undefine_reported(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +sl_status_t dotdot_user_credential_admin_pin_code_undefine_desired( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + attribute_store_undefine_desired(node); + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + + +bool dotdot_user_credential_admin_pin_code_is_reported_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + return attribute_store_is_reported_defined(node); +} + +bool dotdot_user_credential_admin_pin_code_is_desired_defined( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) +{ + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node + = attribute_store_get_first_child_by_type( + endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + return attribute_store_is_desired_defined(node); +} + +sl_status_t dotdot_create_user_credential_admin_pin_code( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + attribute_store_node_t endpoint_node = unify_dotdot_attributes_get_endpoint_node()(unid, endpoint_id); + attribute_store_node_t node = + attribute_store_create_child_if_missing(endpoint_node, + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE); + + return (node != ATTRIBUTE_STORE_INVALID_NODE) ? SL_STATUS_OK : SL_STATUS_FAIL; +} + +bool dotdot_is_any_user_credential_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + if (true == dotdot_is_supported_user_credential_supported_user_unique_identifiers(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_supported_credential_rules(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_supported_credential_types(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_supported_user_types(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_support_credential_checksum(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_support_admin_pin_code(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_support_admin_pin_code_deactivation(unid, endpoint_id)) { + return true; + } + if (true == dotdot_is_supported_user_credential_admin_pin_code(unid, endpoint_id)) { + return true; + } + + return false; +} + +bool dotdot_is_any_user_credential_writable_attribute_supported( + const dotdot_unid_t unid, + const dotdot_endpoint_id_t endpoint_id) { + + return false; } //////////////////////////////////////////////////////////////////////////////// diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp index b725c89f7a..385b26e94e 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_registration.cpp @@ -16807,6 +16807,198 @@ sl_status_t unify_dotdot_attribute_store_registration_init() // clang-format off // clang-format on + { + // uint16 // uint16 // uint16_t + std::string attribute_type_string = "uint16_t"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportedUserUniqueIdentifiers, " + "type: uint16 // uint16_t"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_UNIQUE_IDENTIFIERS, + "ZCL UserCredential SupportedUserUniqueIdentifiers", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // map8 // map8 // uint8_t + std::string attribute_type_string = "uint8_t"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportedCredentialRules, " + "type: map8 // uint8_t"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_RULES, + "ZCL UserCredential SupportedCredentialRules", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // map16 // map16 // uint16_t + std::string attribute_type_string = "uint16_t"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportedCredentialTypes, " + "type: map16 // uint16_t"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_CREDENTIAL_TYPES, + "ZCL UserCredential SupportedCredentialTypes", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // map16 // map16 // uint16_t + std::string attribute_type_string = "uint16_t"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportedUserTypes, " + "type: map16 // uint16_t"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORTED_USER_TYPES, + "ZCL UserCredential SupportedUserTypes", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // bool // bool // bool + std::string attribute_type_string = "bool"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportCredentialChecksum, " + "type: bool // bool"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_CREDENTIAL_CHECKSUM, + "ZCL UserCredential SupportCredentialChecksum", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // bool // bool // bool + std::string attribute_type_string = "bool"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportAdminPinCode, " + "type: bool // bool"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE, + "ZCL UserCredential SupportAdminPinCode", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // bool // bool // bool + std::string attribute_type_string = "bool"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = attribute_storage_type_conversion(attribute_type_string); + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential SupportAdminPinCodeDeactivation, " + "type: bool // bool"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_SUPPORT_ADMIN_PIN_CODE_DEACTIVATION, + "ZCL UserCredential SupportAdminPinCodeDeactivation", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + + { + // string // string // const char* + std::string attribute_type_string = "const char*"; + attribute_store_storage_type_t storage_type = UNKNOWN_STORAGE_TYPE; + + // clang-format off + storage_type = C_STRING_STORAGE_TYPE; + + if (storage_type == UNKNOWN_STORAGE_TYPE) { + sl_log_warning(LOG_TAG, + "Unkown storage type for ZCL UserCredential AdminPinCode, " + "type: string // const char*"); + } + + status |= attribute_store_register_type( + DOTDOT_ATTRIBUTE_ID_USER_CREDENTIAL_ADMIN_PIN_CODE, + "ZCL UserCredential AdminPinCode", + ATTRIBUTE_STORE_INVALID_ATTRIBUTE_TYPE, + storage_type); + } + + // clang-format off + // clang-format on + { // enum8 // enum8 // uint8_t std::string attribute_type_string = "uint8_t"; diff --git a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c index 9d8f2d7085..efad182f51 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c +++ b/components/unify_dotdot_attribute_store/zap-generated/src/unify_dotdot_attribute_store_write_attributes_command_callbacks.c @@ -2394,6 +2394,36 @@ static sl_status_t configuration_parameters_cluster_write_attributes_callback( return SL_STATUS_OK; } //////////////////////////////////////////////////////////////////////////////// +// Start of cluster UserCredential +//////////////////////////////////////////////////////////////////////////////// +// WriteAttribute Callbacks user_credential +static sl_status_t user_credential_cluster_write_attributes_callback( + const dotdot_unid_t unid, + dotdot_endpoint_id_t endpoint_id, + uic_mqtt_dotdot_callback_call_type_t call_type, + uic_mqtt_dotdot_user_credential_state_t attributes, + uic_mqtt_dotdot_user_credential_updated_state_t updated_attributes) +{ + if (false == is_write_attributes_enabled()) { + return SL_STATUS_FAIL; + } + + if (call_type == UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK) { + if (is_automatic_deduction_of_supported_commands_enabled()) { + return dotdot_is_any_user_credential_writable_attribute_supported(unid, endpoint_id) ? + SL_STATUS_OK : SL_STATUS_FAIL; + } else { + return SL_STATUS_FAIL; + } + } + + sl_log_debug(LOG_TAG, + "user_credential: Incoming WriteAttributes command for %s, endpoint %d.\n", + unid, + endpoint_id); + return SL_STATUS_OK; +} +//////////////////////////////////////////////////////////////////////////////// // Start of cluster AoXLocator //////////////////////////////////////////////////////////////////////////////// // WriteAttribute Callbacks aox_locator @@ -2838,6 +2868,9 @@ sl_status_t uic_mqtt_dotdot_set_configuration_parameters_write_attributes_callback( &configuration_parameters_cluster_write_attributes_callback); + uic_mqtt_dotdot_set_user_credential_write_attributes_callback( + &user_credential_cluster_write_attributes_callback); + uic_mqtt_dotdot_set_aox_locator_write_attributes_callback( &aox_locator_cluster_write_attributes_callback); diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c index 7bb885440c..10dfb524b0 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c +++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.c @@ -1256,6 +1256,96 @@ static uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callbac uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_t get_uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback(){ return test_uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback; } +static uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t test_uic_mqtt_dotdot_user_credential_force_read_attributes_callback = NULL; +static uic_mqtt_dotdot_user_credential_write_attributes_callback_t test_uic_mqtt_dotdot_user_credential_write_attributes_callback = NULL; + +uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t get_uic_mqtt_dotdot_user_credential_force_read_attributes_callback(){ + return test_uic_mqtt_dotdot_user_credential_force_read_attributes_callback; +} +uic_mqtt_dotdot_user_credential_write_attributes_callback_t get_uic_mqtt_dotdot_user_credential_write_attributes_callback(){ + return test_uic_mqtt_dotdot_user_credential_write_attributes_callback; +} + +static uic_mqtt_dotdot_user_credential_add_user_callback_t test_uic_mqtt_dotdot_user_credential_add_user_callback = NULL; +uic_mqtt_dotdot_user_credential_add_user_callback_t get_uic_mqtt_dotdot_user_credential_add_user_callback(){ + return test_uic_mqtt_dotdot_user_credential_add_user_callback; +} +static uic_mqtt_dotdot_user_credential_modify_user_callback_t test_uic_mqtt_dotdot_user_credential_modify_user_callback = NULL; +uic_mqtt_dotdot_user_credential_modify_user_callback_t get_uic_mqtt_dotdot_user_credential_modify_user_callback(){ + return test_uic_mqtt_dotdot_user_credential_modify_user_callback; +} +static uic_mqtt_dotdot_user_credential_delete_user_callback_t test_uic_mqtt_dotdot_user_credential_delete_user_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_user_callback_t get_uic_mqtt_dotdot_user_credential_delete_user_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_user_callback; +} +static uic_mqtt_dotdot_user_credential_add_credential_callback_t test_uic_mqtt_dotdot_user_credential_add_credential_callback = NULL; +uic_mqtt_dotdot_user_credential_add_credential_callback_t get_uic_mqtt_dotdot_user_credential_add_credential_callback(){ + return test_uic_mqtt_dotdot_user_credential_add_credential_callback; +} +static uic_mqtt_dotdot_user_credential_modify_credential_callback_t test_uic_mqtt_dotdot_user_credential_modify_credential_callback = NULL; +uic_mqtt_dotdot_user_credential_modify_credential_callback_t get_uic_mqtt_dotdot_user_credential_modify_credential_callback(){ + return test_uic_mqtt_dotdot_user_credential_modify_credential_callback; +} +static uic_mqtt_dotdot_user_credential_delete_credential_callback_t test_uic_mqtt_dotdot_user_credential_delete_credential_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_credential_callback_t get_uic_mqtt_dotdot_user_credential_delete_credential_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_credential_callback; +} +static uic_mqtt_dotdot_user_credential_delete_all_users_callback_t test_uic_mqtt_dotdot_user_credential_delete_all_users_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_all_users_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_users_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_all_users_callback; +} +static uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback; +} +static uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback; +} +static uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback; +} +static uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback = NULL; +uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback(){ + return test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback; +} +static uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback = NULL; +uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t get_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback(){ + return test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback; +} +static uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback = NULL; +uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t get_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback(){ + return test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback; +} +static uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback = NULL; +uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t get_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback(){ + return test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback; +} +static uic_mqtt_dotdot_user_credential_credential_association_callback_t test_uic_mqtt_dotdot_user_credential_credential_association_callback = NULL; +uic_mqtt_dotdot_user_credential_credential_association_callback_t get_uic_mqtt_dotdot_user_credential_credential_association_callback(){ + return test_uic_mqtt_dotdot_user_credential_credential_association_callback; +} +static uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback = NULL; +uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t get_uic_mqtt_dotdot_user_credential_get_user_checksum_callback(){ + return test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback; +} +static uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback = NULL; +uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t get_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback(){ + return test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback; +} +static uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback = NULL; +uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t get_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback(){ + return test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback; +} +static uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback = NULL; +uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t get_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback(){ + return test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback; +} +static uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback = NULL; +uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t get_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback(){ + return test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback; +} static uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t test_uic_mqtt_dotdot_aox_locator_force_read_attributes_callback = NULL; static uic_mqtt_dotdot_aox_locator_write_attributes_callback_t test_uic_mqtt_dotdot_aox_locator_write_attributes_callback = NULL; @@ -2868,6 +2958,116 @@ void uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_ { test_uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback = callback; } +void set_uic_mqtt_dotdot_user_credential_force_read_attributes_callback_stub( + const uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_force_read_attributes_callback = callback; +} +void set_uic_mqtt_dotdot_user_credential_write_attributes_callback_stub( + const uic_mqtt_dotdot_user_credential_write_attributes_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_write_attributes_callback = callback; +} +void uic_mqtt_dotdot_user_credential_add_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_add_user_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_add_user_callback = callback; +} +void uic_mqtt_dotdot_user_credential_modify_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_modify_user_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_modify_user_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_user_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_user_callback = callback; +} +void uic_mqtt_dotdot_user_credential_add_credential_callback_set_stub( + const uic_mqtt_dotdot_user_credential_add_credential_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_add_credential_callback = callback; +} +void uic_mqtt_dotdot_user_credential_modify_credential_callback_set_stub( + const uic_mqtt_dotdot_user_credential_modify_credential_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_modify_credential_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_credential_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_credential_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_credential_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_users_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_users_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_all_users_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback = callback; +} +void uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set_stub( + const uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback = callback; +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback = callback; +} +void uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback = callback; +} +void uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback = callback; +} +void uic_mqtt_dotdot_user_credential_credential_association_callback_set_stub( + const uic_mqtt_dotdot_user_credential_credential_association_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_credential_association_callback = callback; +} +void uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set_stub( + const uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback = callback; +} +void uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set_stub( + const uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback = callback; +} +void uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set_stub( + const uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback = callback; +} +void uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set_stub( + const uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback = callback; +} +void uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set_stub( + const uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t callback, int cmock_num_calls) +{ + test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback = callback; +} void set_uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_stub( const uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t callback, int cmock_num_calls) { @@ -3862,6 +4062,72 @@ void setUp() test_uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback = NULL; uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_set_Stub( &uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_force_read_attributes_callback = NULL; + uic_mqtt_dotdot_set_user_credential_force_read_attributes_callback_Stub( + &set_uic_mqtt_dotdot_user_credential_force_read_attributes_callback_stub); + test_uic_mqtt_dotdot_user_credential_write_attributes_callback = NULL; + uic_mqtt_dotdot_set_user_credential_write_attributes_callback_Stub( + &set_uic_mqtt_dotdot_user_credential_write_attributes_callback_stub); + test_uic_mqtt_dotdot_user_credential_add_user_callback = NULL; + uic_mqtt_dotdot_user_credential_add_user_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_add_user_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_modify_user_callback = NULL; + uic_mqtt_dotdot_user_credential_modify_user_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_modify_user_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_user_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_user_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_user_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_add_credential_callback = NULL; + uic_mqtt_dotdot_user_credential_add_credential_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_add_credential_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_modify_credential_callback = NULL; + uic_mqtt_dotdot_user_credential_modify_credential_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_modify_credential_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_credential_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_credential_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_credential_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_all_users_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_all_users_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_all_users_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback = NULL; + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback = NULL; + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback = NULL; + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback = NULL; + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_credential_association_callback = NULL; + uic_mqtt_dotdot_user_credential_credential_association_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_credential_association_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback = NULL; + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_get_user_checksum_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback = NULL; + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback = NULL; + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback = NULL; + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_set_stub); + test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback = NULL; + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set_Stub( + &uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_set_stub); test_uic_mqtt_dotdot_aox_locator_force_read_attributes_callback = NULL; uic_mqtt_dotdot_set_aox_locator_force_read_attributes_callback_Stub( &set_uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_stub); @@ -4669,6 +4935,14 @@ void test_automatic_deduction_of_supported_commands() TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_name_and_location_name(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_name_and_location_location(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_configuration_parameters_configuration_parameters(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_supported_user_unique_identifiers(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_supported_credential_rules(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_supported_credential_types(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_supported_user_types(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_support_credential_checksum(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_support_admin_pin_code(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_support_admin_pin_code_deactivation(expected_unid,expected_endpoint_id) ); + TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_user_credential_admin_pin_code(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_aox_locator_reporting_mode(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_aox_locator_position_and_orientation_valid(expected_unid,expected_endpoint_id) ); TEST_ASSERT_EQUAL(SL_STATUS_OK, dotdot_create_aox_locator_position_and_orientation(expected_unid,expected_endpoint_id) ); @@ -7772,6 +8046,330 @@ void test_automatic_deduction_of_supported_commands() )); } + if (NULL != test_uic_mqtt_dotdot_user_credential_add_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + UserTypeEnum user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + bool user_active_state_value; + memset(&user_active_state_value, 0x00, sizeof(user_active_state_value)); + CredRule credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint16_t expiring_timeout_minutes_value; + memset(&expiring_timeout_minutes_value, 0x00, sizeof(expiring_timeout_minutes_value)); + UserNameEncodingType user_name_encoding_value; + memset(&user_name_encoding_value, 0x00, sizeof(user_name_encoding_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_add_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + user_type_value, + + user_active_state_value, + + credential_rule_value, + + user_name_value, + + expiring_timeout_minutes_value, + + user_name_encoding_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_modify_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + UserTypeEnum user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + bool user_active_state_value; + memset(&user_active_state_value, 0x00, sizeof(user_active_state_value)); + CredRule credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint16_t expiring_timeout_minutes_value; + memset(&expiring_timeout_minutes_value, 0x00, sizeof(expiring_timeout_minutes_value)); + UserNameEncodingType user_name_encoding_value; + memset(&user_name_encoding_value, 0x00, sizeof(user_name_encoding_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_modify_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + user_type_value, + + user_active_state_value, + + credential_rule_value, + + user_name_value, + + expiring_timeout_minutes_value, + + user_name_encoding_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_add_credential_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_add_credential_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_data_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_modify_credential_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_modify_credential_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_data_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_credential_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_credential_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_users_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_all_users_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback) { + // Dummy command parameters + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + uint8_t credential_learn_timeout_value; + memset(&credential_learn_timeout_value, 0x00, sizeof(credential_learn_timeout_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_learn_timeout_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + uint8_t credential_learn_timeout_value; + memset(&credential_learn_timeout_value, 0x00, sizeof(credential_learn_timeout_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_learn_timeout_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_association_callback) { + // Dummy command parameters + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t source_user_uniqueid_value; + memset(&source_user_uniqueid_value, 0x00, sizeof(source_user_uniqueid_value)); + uint16_t source_credential_slot_value; + memset(&source_credential_slot_value, 0x00, sizeof(source_credential_slot_value)); + uint16_t destination_user_uniqueid_value; + memset(&destination_user_uniqueid_value, 0x00, sizeof(destination_user_uniqueid_value)); + uint16_t destination_credential_slot_value; + memset(&destination_credential_slot_value, 0x00, sizeof(destination_credential_slot_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_credential_association_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value, + + source_user_uniqueid_value, + + source_credential_slot_value, + + destination_user_uniqueid_value, + + destination_credential_slot_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback) { + // Dummy command parameters + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback) { + // Dummy command parameters + const char* pin_code_value; + memset(&pin_code_value, 0x00, sizeof(pin_code_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + pin_code_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_FAIL, test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } if (NULL != test_uic_mqtt_dotdot_aox_locator_iq_report_callback) { // Dummy command parameters const char* tag_unid_value; @@ -10951,6 +11549,330 @@ void test_automatic_deduction_of_supported_commands() )); } + if (NULL != test_uic_mqtt_dotdot_user_credential_add_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + UserTypeEnum user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + bool user_active_state_value; + memset(&user_active_state_value, 0x00, sizeof(user_active_state_value)); + CredRule credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint16_t expiring_timeout_minutes_value; + memset(&expiring_timeout_minutes_value, 0x00, sizeof(expiring_timeout_minutes_value)); + UserNameEncodingType user_name_encoding_value; + memset(&user_name_encoding_value, 0x00, sizeof(user_name_encoding_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_add_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + user_type_value, + + user_active_state_value, + + credential_rule_value, + + user_name_value, + + expiring_timeout_minutes_value, + + user_name_encoding_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_modify_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + UserTypeEnum user_type_value; + memset(&user_type_value, 0x00, sizeof(user_type_value)); + bool user_active_state_value; + memset(&user_active_state_value, 0x00, sizeof(user_active_state_value)); + CredRule credential_rule_value; + memset(&credential_rule_value, 0x00, sizeof(credential_rule_value)); + const char* user_name_value; + memset(&user_name_value, 0x00, sizeof(user_name_value)); + uint16_t expiring_timeout_minutes_value; + memset(&expiring_timeout_minutes_value, 0x00, sizeof(expiring_timeout_minutes_value)); + UserNameEncodingType user_name_encoding_value; + memset(&user_name_encoding_value, 0x00, sizeof(user_name_encoding_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_modify_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + user_type_value, + + user_active_state_value, + + credential_rule_value, + + user_name_value, + + expiring_timeout_minutes_value, + + user_name_encoding_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_add_credential_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_add_credential_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_data_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_modify_credential_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + const char* credential_data_value; + memset(&credential_data_value, 0x00, sizeof(credential_data_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_modify_credential_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_data_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_credential_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_credential_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_users_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_all_users_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback) { + // Dummy command parameters + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + uint8_t credential_learn_timeout_value; + memset(&credential_learn_timeout_value, 0x00, sizeof(credential_learn_timeout_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_learn_timeout_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t credential_slot_value; + memset(&credential_slot_value, 0x00, sizeof(credential_slot_value)); + uint8_t credential_learn_timeout_value; + memset(&credential_learn_timeout_value, 0x00, sizeof(credential_learn_timeout_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value, + + credential_type_value, + + credential_slot_value, + + credential_learn_timeout_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_credential_association_callback) { + // Dummy command parameters + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + uint16_t source_user_uniqueid_value; + memset(&source_user_uniqueid_value, 0x00, sizeof(source_user_uniqueid_value)); + uint16_t source_credential_slot_value; + memset(&source_credential_slot_value, 0x00, sizeof(source_credential_slot_value)); + uint16_t destination_user_uniqueid_value; + memset(&destination_user_uniqueid_value, 0x00, sizeof(destination_user_uniqueid_value)); + uint16_t destination_credential_slot_value; + memset(&destination_credential_slot_value, 0x00, sizeof(destination_credential_slot_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_credential_association_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value, + + source_user_uniqueid_value, + + source_credential_slot_value, + + destination_user_uniqueid_value, + + destination_credential_slot_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback) { + // Dummy command parameters + uint16_t user_uniqueid_value; + memset(&user_uniqueid_value, 0x00, sizeof(user_uniqueid_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_get_user_checksum_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + user_uniqueid_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback) { + // Dummy command parameters + CredType credential_type_value; + memset(&credential_type_value, 0x00, sizeof(credential_type_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + credential_type_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback) { + // Dummy command parameters + const char* pin_code_value; + memset(&pin_code_value, 0x00, sizeof(pin_code_value)); + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + , + pin_code_value + + )); + } + if (NULL != test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback) { + // Dummy command parameters + // Invoke with support check + TEST_ASSERT_EQUAL(SL_STATUS_OK, test_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback(expected_unid,expected_endpoint_id,UIC_MQTT_DOTDOT_CALLBACK_TYPE_SUPPORT_CHECK + + )); + } if (NULL != test_uic_mqtt_dotdot_aox_locator_iq_report_callback) { // Dummy command parameters const char* tag_unid_value; diff --git a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h index a868e2db1c..0a9d3e6229 100644 --- a/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h +++ b/components/unify_dotdot_attribute_store/zap-generated/test/unify_dotdot_attribute_store_test.h @@ -766,6 +766,70 @@ uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback_t get_uic_mqtt_dotdot_configuration_parameters_discover_parameter_range_callback(); + uic_mqtt_dotdot_user_credential_force_read_attributes_callback_t get_uic_mqtt_dotdot_user_credential_force_read_attributes_callback(); + uic_mqtt_dotdot_user_credential_write_attributes_callback_t get_uic_mqtt_dotdot_user_credential_write_attributes_callback(); + + + uic_mqtt_dotdot_user_credential_add_user_callback_t get_uic_mqtt_dotdot_user_credential_add_user_callback(); + + + uic_mqtt_dotdot_user_credential_modify_user_callback_t get_uic_mqtt_dotdot_user_credential_modify_user_callback(); + + + uic_mqtt_dotdot_user_credential_delete_user_callback_t get_uic_mqtt_dotdot_user_credential_delete_user_callback(); + + + uic_mqtt_dotdot_user_credential_add_credential_callback_t get_uic_mqtt_dotdot_user_credential_add_credential_callback(); + + + uic_mqtt_dotdot_user_credential_modify_credential_callback_t get_uic_mqtt_dotdot_user_credential_modify_credential_callback(); + + + uic_mqtt_dotdot_user_credential_delete_credential_callback_t get_uic_mqtt_dotdot_user_credential_delete_credential_callback(); + + + uic_mqtt_dotdot_user_credential_delete_all_users_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_users_callback(); + + + uic_mqtt_dotdot_user_credential_delete_all_credentials_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_callback(); + + + uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_by_type_callback(); + + + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_callback(); + + + uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback_t get_uic_mqtt_dotdot_user_credential_delete_all_credentials_for_user_by_type_callback(); + + + uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback_t get_uic_mqtt_dotdot_user_credential_credential_learn_start_add_callback(); + + + uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback_t get_uic_mqtt_dotdot_user_credential_credential_learn_start_modify_callback(); + + + uic_mqtt_dotdot_user_credential_credential_learn_stop_callback_t get_uic_mqtt_dotdot_user_credential_credential_learn_stop_callback(); + + + uic_mqtt_dotdot_user_credential_credential_association_callback_t get_uic_mqtt_dotdot_user_credential_credential_association_callback(); + + + uic_mqtt_dotdot_user_credential_get_user_checksum_callback_t get_uic_mqtt_dotdot_user_credential_get_user_checksum_callback(); + + + uic_mqtt_dotdot_user_credential_get_credential_checksum_callback_t get_uic_mqtt_dotdot_user_credential_get_credential_checksum_callback(); + + + uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback_t get_uic_mqtt_dotdot_user_credential_get_all_users_checksum_callback(); + + + uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback_t get_uic_mqtt_dotdot_user_credential_set_admin_pin_code_callback(); + + + uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback_t get_uic_mqtt_dotdot_user_credential_deactivate_admin_pin_code_callback(); + + uic_mqtt_dotdot_aox_locator_force_read_attributes_callback_t get_uic_mqtt_dotdot_aox_locator_force_read_attributes_callback(); uic_mqtt_dotdot_aox_locator_write_attributes_callback_t get_uic_mqtt_dotdot_aox_locator_write_attributes_callback(); diff --git a/helper.mk b/helper.mk index 7eb3d4435c..0d52b54acc 100755 --- a/helper.mk +++ b/helper.mk @@ -25,6 +25,7 @@ packages+=nlohmann-json3-dev # TODO: remove for offline build packages+=curl wget python3-pip packages+=time +packages+=yarnpkg rust_url?=https://sh.rustup.rs RUST_VERSION?=1.65.0 @@ -36,7 +37,7 @@ exes+=${zpc_exe} zpc_cmake_options?=\ -DBUILD_AOXPC=OFF \ -DBUILD_CPCD=OFF \ - -DBUILD_DEV_GUI=OFF \ + -DBUILD_DEV_GUI=ON \ -DBUILD_EMD=OFF \ -DBUILD_EPC=OFF \ -DBUILD_GMS=OFF \