Skip to content

Commit

Permalink
uic: zpc: UIC-3277:Time Parameters CC
Browse files Browse the repository at this point in the history
(cherry picked from commit 320f92bf980778fcdb5f9dc4f97fba2b24233469)
Forwarded: #11
Signed-off-by: Philippe Coval <philippe.coval@silabs.com>
  • Loading branch information
Thirsrin authored and rzr committed Feb 5, 2025
1 parent 30afce6 commit af84a42
Show file tree
Hide file tree
Showing 9 changed files with 525 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ add_library(
src/zwave_command_class_thermostat_fan_state.c
src/zwave_command_class_thermostat_setpoint.cpp
src/zwave_command_class_thermostat_operating_state.c
src/zwave_command_class_time_parameters.cpp
src/zwave_command_class_time.c
src/zwave_command_class_user_code.c
src/zwave_command_class_version.c
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef PLATFORM_DATE_TIME_H
#define PLATFORM_DATE_TIME_H

#include "sl_status.h"
typedef struct {
int sec; /* seconds after the minute [0-60] */
int min; /* minutes after the hour [0-59] */
Expand All @@ -28,4 +29,10 @@ typedef struct {
*/
date_time_t platform_get_date_time();

/**
* @brief platform abstraction for setting local system time.
*/

sl_status_t platform_set_date_time(const date_time_t *new_time);

#endif
Original file line number Diff line number Diff line change
@@ -1,21 +1,57 @@
#include "platform_date_time.h"
#include <time.h>
#include <sys/time.h>

// Static variable to store time offset
static time_t time_offset = 0;

date_time_t platform_get_date_time()
{
date_time_t return_time = {0};
time_t current_time = {0};
struct tm local_time = {0};
date_time_t return_time = {0};
time_t current_time;
current_time = time(NULL);

current_time += time_offset;
struct tm *local_time = localtime(&current_time);

if (local_time == NULL) {
return return_time;
}

// Populate return_time with the adjusted values
return_time.sec = local_time->tm_sec;
return_time.min = local_time->tm_min;
return_time.hour = local_time->tm_hour;
return_time.day = local_time->tm_mday;
return_time.mon = local_time->tm_mon;
return_time.year = local_time->tm_year;

time(&current_time);
if (!localtime_r(&current_time, &local_time))
return return_time;
}

sl_status_t platform_set_date_time(const date_time_t *new_time)
{
struct tm tm = {0};

// Populate the tm structure with the values from new_time
tm.tm_year = new_time->year; // tm_year is years since 1900
tm.tm_mon = new_time->mon; // tm_mon is 0-11
tm.tm_mday = new_time->day;
tm.tm_hour = new_time->hour;
tm.tm_min = new_time->min;
tm.tm_sec = new_time->sec;

// Convert tm structure to time_t
time_t time_in_secs = mktime(&tm);
if (time_in_secs == (time_t)(-1)) {
return SL_STATUS_FAIL;
}

// Get the current system time
time_t real_time_in_secs = time(NULL);

// Calculate the time offset
time_offset = time_in_secs - real_time_in_secs;

return_time.sec = local_time.tm_sec;
return_time.min = local_time.tm_min;
return_time.hour = local_time.tm_hour;
return_time.day = local_time.tm_mday;
return_time.mon = local_time.tm_mon;
return_time.year = local_time.tm_year;
return return_time;
return SL_STATUS_OK; // Return success status
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
******************************************************************************
* 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_time_parameters.h"
#include "ZW_classcmd.h"
#include "zwave_command_handler.h"
#include "zwave_command_class_indices.h"
#include "zwave_command_classes_utils.h"
#include "assert.h"

#ifdef __cplusplus
extern "C" {
#endif

#include <time.h>
#include "platform_date_time.h"

#include "zwave_controller_connection_info.h"
#include "zwave_tx.h"

///////////////////////////////////////////////////////////////////////////////
// Private functions, used to handle individual incoming commands.
///////////////////////////////////////////////////////////////////////////////

/**
* @brief Command handler for the Time parameters Get command.
*
* The Gateway will send return a Time Report frame containing
* the current time (year, month, day, hours, minutes and seconds).
*
* @param connection_info Info about the connection properties of this frame.
* @returns sl_status_t indicating the outcome of returning the time.
*/
static sl_status_t zwave_command_class_time_parameters_get(
const zwave_controller_connection_info_t *connection_info)
{
if (connection_info && connection_info->local.is_multicast) {
return SL_STATUS_OK;
}

date_time_t time = platform_get_date_time();
ZW_TIME_PARAMETERS_REPORT_FRAME report
= {.cmdClass = COMMAND_CLASS_TIME_PARAMETERS,
.cmd = TIME_PARAMETERS_REPORT,
.year1 = static_cast<uint8_t>((time.year + 1900) >> 8), //MSB
.year2 = static_cast<uint8_t>((time.year + 1900) & 0xFF), //LSB
.month = static_cast<uint8_t>(time.mon + 1),
.day = static_cast<uint8_t>(time.day),
.hourUtc = static_cast<uint8_t>(time.hour & 0xF),
.minuteUtc = static_cast<uint8_t>(time.min),
.secondUtc = static_cast<uint8_t>(time.sec)};

return zwave_command_class_send_report(connection_info,
sizeof(report),
(uint8_t *)&report);
}

sl_status_t
zwave_command_class_time_parameters_set(const uint8_t *frame_data,
uint16_t frame_length)
{
if (frame_length < sizeof(ZW_TIME_PARAMETERS_SET_FRAME)) {
return SL_STATUS_FAIL;
}

// Extract and parse the time from the frame data
uint16_t year = (frame_data[2] << 8) | frame_data[3];
uint8_t month = frame_data[4];
uint8_t day = frame_data[5];
uint8_t hour = frame_data[6];
uint8_t minute = frame_data[7];
uint8_t second = frame_data[8];

// Create a date_time_t structure and populate it
date_time_t new_time;
new_time.year = year - 1900;
new_time.mon = month - 1;
new_time.day = day;
new_time.hour = hour;
new_time.min = minute;
new_time.sec = second;

// Update the system time
if (platform_set_date_time(&new_time) != SL_STATUS_OK) {
return SL_STATUS_FAIL;
}

return SL_STATUS_OK;
}

///////////////////////////////////////////////////////////////////////////////
// Public interface functions
///////////////////////////////////////////////////////////////////////////////
sl_status_t zwave_command_class_time_parameters_support_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;
}

assert(frame_data[COMMAND_CLASS_INDEX] == COMMAND_CLASS_TIME_PARAMETERS);

switch (frame_data[COMMAND_INDEX]) {
case TIME_PARAMETERS_GET:
return zwave_command_class_time_parameters_get(connection_info);
case TIME_PARAMETERS_SET:
return zwave_command_class_time_parameters_set(frame_data, frame_length);

default:
return SL_STATUS_NOT_SUPPORTED;
}
}

sl_status_t zwave_command_class_time_parameters_init()
{
zwave_command_handler_t handler = {0};
handler.support_handler
= &zwave_command_class_time_parameters_support_handler;
handler.control_handler = NULL;
handler.minimal_scheme = ZWAVE_CONTROLLER_ENCAPSULATION_NONE;
handler.manual_security_validation = false;
handler.command_class = COMMAND_CLASS_TIME_PARAMETERS;
handler.version = TIME_PARAMETERS_VERSION;
handler.command_class_name = "Time Parameters";

return zwave_command_handler_register_handler(handler);
}

#ifdef __cplusplus
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
******************************************************************************
* 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_TIME_PARAMETERS_H
#define ZWAVE_COMMAND_CLASS_TIME_PARAMETERS_H

#include "sl_status.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "zwave_rx.h"

/**
* @brief This function initialize the time parameters Command Class handler
*
* @return SL_STATUS_OK on success, any other error code for an error.
*/
sl_status_t zwave_command_class_time_parameters_init();

/**
* @brief Handles incoming time parameters encapsulated commands
*
* @param connection_info Info about the connection properties of this frame.
* @param frame_data The data payload of this frame.
* @param frame_length The length of this frame.
* @returns sl_status_t representing the outcome of receiving the frame
* In case where the command is controlled, it should be set to SL_STATUS_OK,
* even when encountering some parsing errors
* In case where the command is supported, it should be set to the @ref sl_status_t
* corresponding to the correct time Status code. Refer to @ref zwave_command_handler_t
*/
sl_status_t zwave_command_class_time_parameters_support_handler(
const zwave_controller_connection_info_t *connection_info,
const uint8_t *frame_data,
uint16_t frame_length);


/**
* @brief Handles time parameters set commands
*
* @param frame_data The data payload of this frame.
* @param frame_length The length of this frame.
* @returns SL_STATUS_OK on success, any other error code for an error.
*/

sl_status_t
zwave_command_class_time_parameters_set(const uint8_t *frame_data,
uint16_t frame_length);

#ifdef __cplusplus
}
#endif

#endif //ZWAVE_COMMAND_CLASS_TIME_PARAMETERS_H
/** @} end zwave_command_class_time_parameters */
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "zwave_command_class_thermostat_operating_state.h"
#include "zwave_command_class_version.h"
#include "zwave_command_class_wake_up.h"
#include "zwave_command_class_time_parameters.h"
#include "zwave_command_class_time.h"
#include "zwave_command_class_user_code.h"
#include "zwave_command_class_basic.h"
Expand Down Expand Up @@ -119,6 +120,7 @@ sl_status_t zwave_command_classes_init()
status |= zwave_command_class_thermostat_fan_state_init();
status |= zwave_command_class_thermostat_setpoint_init();
status |= zwave_command_class_thermostat_operating_state_init();
status |= zwave_command_class_time_parameters_init();
status |= zwave_command_class_time_init();
status |= zwave_command_class_transport_service_init();
status |= zwave_command_class_user_code_init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ target_add_unittest(
zwave_command_class_test_helpers
${MOCK_LIBS})

target_add_unittest(
zwave_command_classes
NAME
zwave_command_class_time_parameters_test
SOURCES
zwave_command_class_time_parameters_test.c
DEPENDS
zwave_command_class_test_helpers
${MOCK_LIBS})

target_add_unittest(
zwave_command_classes
NAME
Expand Down Expand Up @@ -796,7 +806,7 @@ target_add_unittest(
uic_attribute_resolver_mock
zpc_attribute_resolver_mock
)

# Humidity Control Mode test
target_add_unittest(
zwave_command_classes
Expand Down Expand Up @@ -841,5 +851,4 @@ target_add_unittest(
uic_attribute_resolver_mock
zpc_attribute_resolver_mock
uic_dotdot_mqtt_mock)



Loading

0 comments on commit af84a42

Please sign in to comment.