Skip to content

Commit

Permalink
fix basic maping and add new id for Thermostat
Browse files Browse the repository at this point in the history
  • Loading branch information
amatilda committed Oct 30, 2024
1 parent 0844e37 commit a3fb8b4
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 167 deletions.
11 changes: 4 additions & 7 deletions hardware/arduino/zunoG2/cores/ZWSupport/ZWCCBasic.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ void __zuno_BasicUniversalDimingStop(uint8_t channel) {
break ;
}
}

uint8_t __zuno_CCThermostatModeTobasicGet(size_t channel);
void __zuno_BasicUniversalGetCurrentValueDurationTargetValue(uint8_t channel, uint8_t *current_value, uint8_t *duration_table_8, uint8_t *target_value) {
size_t type;
size_t currentValue;
Expand Down Expand Up @@ -129,12 +129,9 @@ void __zuno_BasicUniversalGetCurrentValueDurationTargetValue(uint8_t channel, ui
#endif
default:
switch (type) {
#if defined(WITH_CC_THERMOSTAT_MODE) || defined(WITH_CC_THERMOSTAT_SETPOINT)
#if defined(WITH_CC_THERMOSTAT_MODE) || defined(WITH_CC_THERMOSTAT_SETPOINT)
case ZUNO_THERMOSTAT_CHANNEL_NUMBER:
#endif
currentValue = __zuno_BasicUniversalGetter1P(channel);
currentValue = currentValue ? 0xFF : 0x00;
currentValue = __zuno_CCThermostatModeTobasicGet(channel);
break;
#endif
default:
Expand All @@ -159,7 +156,7 @@ void __zuno_BasicUniversalGetCurrentValueDurationTargetValue(uint8_t channel, ui
}

#ifdef WITH_CC_BASIC
size_t zuno_CCThermostatModeTobasic(size_t channel, size_t value);
uint8_t __zuno_CCThermostatModeTobasicSet(uint8_t channel, uint8_t value);
int zuno_CCSoundSwitchBasicSet(size_t channel, size_t toneIdentifier, const ZUNOCommandHandlerOption_t *options);
static int _basic_set(byte channel, const ZwBasicSetFrame_t *paket, const ZUNOCommandHandlerOption_t *options) {
size_t value;
Expand All @@ -178,7 +175,7 @@ static int _basic_set(byte channel, const ZwBasicSetFrame_t *paket, const ZUNOCo
switch (type) {
#if defined(WITH_CC_THERMOSTAT_MODE) || defined(WITH_CC_THERMOSTAT_SETPOINT)
case ZUNO_THERMOSTAT_CHANNEL_NUMBER:
value = zuno_CCThermostatModeTobasic(channel, value);
value = __zuno_CCThermostatModeTobasicSet(channel, value);
break;
#endif
#ifdef WITH_CC_SWITCH_BINARY
Expand Down
225 changes: 152 additions & 73 deletions hardware/arduino/zunoG2/cores/ZWSupport/ZWCCThermostat.c
Original file line number Diff line number Diff line change
@@ -1,80 +1,161 @@
#include "Arduino.h"
#include "ZWCCThermostat.h"
#if defined(WITH_CC_THERMOSTAT_MODE) || defined(WITH_CC_THERMOSTAT_SETPOINT)

static uint32_t _get_compresed_combi_value(uint8_t channel)
{
return (ZUNO_CFG_CHANNEL(channel).params[0]);
}

static uint32_t _get_mode_support_mask(uint8_t channel)
{
uint32_t mask;
uint8_t sub_type;
uint8_t params1;

sub_type = ZUNO_CFG_CHANNEL(channel).sub_type;
mask = ((sub_type & (THERMOSTAT_FLAGS_OFF|THERMOSTAT_FLAGS_HEAT|THERMOSTAT_FLAGS_COOL)) | ((sub_type & (THERMOSTAT_FLAGS_FURNACE)) << 4));
mask = mask | (((sub_type & (THERMOSTAT_FLAGS_DRY|THERMOSTAT_FLAGS_MOIST|THERMOSTAT_FLAGS_AUTO_CHANGEOVER)) << 0x4) | ((sub_type & (THERMOSTAT_FLAGS_FULL_POWER)) << 0x8));
params1 = ZUNO_CFG_CHANNEL(channel).params[0x1];
mask = mask | (((params1 << 0x8) << 0x3) & (THERMOSTAT_FLAGS_MASK_PARAM_01 << 0x3));
return (mask);
}

static bool _get_termostat_set_point_is_valid(uint8_t channel, uint8_t componentId)
{
uint32_t support_mode_mask;

support_mode_mask = _get_mode_support_mask(channel);
if ((support_mode_mask & (0x1 << componentId)) != 0x0)
return (true);
return (false);
}

static uint32_t _get_termostat_set_point_support_mask_interpretation_a(uint8_t channel)
{
uint32_t mask;
uint32_t mask_a;

mask = _get_mode_support_mask(channel);
mask_a = (mask & ((0x1 << THERMOSTAT_MODE_FURNACE)|(0x1 << THERMOSTAT_MODE_DRY)|(0x1 << THERMOSTAT_MODE_MOIST)|(0x1 << THERMOSTAT_MODE_AUTO_CHANGEOVER)|(0x1 << THERMOSTAT_MODE_FULL_POWER)|
(0x1 << THERMOSTAT_MODE_ENERGY_SAVE_HEATING)|(0x1 << THERMOSTAT_MODE_ENERGY_SAVE_COOLING)|(0x1 << THERMOSTAT_MODE_AWAY_COOLING)|(0x1 << THERMOSTAT_MODE_AWAY_HEATING))) >> 0x4;
mask_a = mask_a | (mask & ((0x1 << THERMOSTAT_MODE_HEAT)|(0x1 << THERMOSTAT_MODE_COOL)));
return (mask_a);
}

static uint32_t _get_termostat_mode_support_mask(uint8_t channel)
{
uint32_t mask;

mask = _get_mode_support_mask(channel);
if ((mask & ((0x1 << THERMOSTAT_MODE_AWAY_HEATING) | (0x1 << THERMOSTAT_MODE_AWAY_COOLING))) != 0x0)
mask = (mask & (~((0x1 << THERMOSTAT_MODE_AWAY_HEATING) | (0x1 << THERMOSTAT_MODE_AWAY_COOLING)))) | (0x1 << THERMOSTAT_MODE_AWAY_HEATING);
return (mask);
}

static bool _termostat_mode_is_valid(uint8_t channel, uint8_t componentId)
{
uint32_t support_mode_mask;

support_mode_mask = _get_termostat_mode_support_mask(channel);
if ((support_mode_mask & (0x1 << componentId)) != 0x0)
return (true);
return (false);
}

static int _supported_report_mode(uint8_t channel, ZUNOCommandPacketReport_t *frame_report) {//Processed to get the value of the thermostatmode components
ZwThermostatModeSupportedReportFrame_t *lp;
uint8_t sub_type;
ZwThermostatModeSupportedReportFrame_t *report;
uint32_t support_mode_mask;
uint8_t len;

lp = (ZwThermostatModeSupportedReportFrame_t *)frame_report->info.packet.cmd;
sub_type = ZUNO_CFG_CHANNEL(channel).sub_type;//It contains a bitmask of thermostat
support_mode_mask = _get_termostat_mode_support_mask(channel);
report = (ZwThermostatModeSupportedReportFrame_t *)frame_report->info.packet.cmd;
len = ((((sizeof(support_mode_mask) * 0x8) - __builtin_clz(support_mode_mask)) >> 0x3) + 0x1);
// lp->byte2.cmdClass = COMMAND_CLASS_THERMOSTAT_MODE; set in - fillOutgoingPacket
// lp->byte2.cmd = THERMOSTAT_MODE_SUPPORTED_REPORT; set in - fillOutgoingPacket
lp->byte2.bitMask1 = (sub_type & 0x07) | ((sub_type & 0x08) << 4);
sub_type >>= 4;
lp->byte2.bitMask2 = (sub_type & 0x07) | ((sub_type & 0x08) << 4);
frame_report->info.packet.len = sizeof(lp->byte2);
memcpy(&report->bitMask[0x0], &support_mode_mask, len);
frame_report->info.packet.len = sizeof(report[0x0]) + len;
return (ZUNO_COMMAND_ANSWERED);
}

static size_t _bitTestComponentId(size_t channel, size_t componentId) {
size_t offset;
static const uint8_t _termostat_mode_basic_null[] = {THERMOSTAT_MODE_OFF, THERMOSTAT_MODE_ENERGY_SAVE_HEATING, THERMOSTAT_MODE_ENERGY_SAVE_COOLING, THERMOSTAT_MODE_AWAY_HEATING};
static const uint8_t _termostat_mode_basic[] = {THERMOSTAT_MODE_HEAT, THERMOSTAT_MODE_COOL};

switch (componentId) {
case THERMOSTAT_MODE_OFF:
offset = THERMOSTAT_FLAGS_OFF;
break ;
case THERMOSTAT_MODE_HEAT:
offset = THERMOSTAT_FLAGS_HEAT;
break ;
case THERMOSTAT_MODE_COOL:
offset = THERMOSTAT_FLAGS_COOL;
break ;
case THERMOSTAT_MODE_FURNACE:
offset = THERMOSTAT_FLAGS_FURNACE;
break ;
case THERMOSTAT_MODE_DRY:
offset = THERMOSTAT_FLAGS_DRY;
break ;
case THERMOSTAT_MODE_MOIST:
offset = THERMOSTAT_FLAGS_MOIST;
break ;
case THERMOSTAT_MODE_AUTO_CHANGEOVER:
offset = THERMOSTAT_FLAGS_AUTO_CHANGEOVER;
break ;
#if THERMOSTAT_MODE_AUTO_CHANGEOVER != THERMOSTAT_MODE_AUTO
case THERMOSTAT_MODE_AUTO:
offset = THERMOSTAT_FLAGS_AUTO;
break ;
#endif
case THERMOSTAT_MODE_FULL_POWER:
offset = THERMOSTAT_FLAGS_FULL_POWER;
break ;
default:
return (false);
break ;
static int8_t _termostat_mode_basic_set(const uint8_t *array, size_t lenght, uint32_t support_mode_mask) {
size_t i;

i = 0x0;
while (i < lenght)
{
if ((support_mode_mask & (0x1 << array[i])) != 0x0)
return (array[i]);
i++;
}
if ((ZUNO_CFG_CHANNEL(channel).sub_type & offset) != 0x0)
return (true);
return (false);
return (-1);
}

size_t zuno_CCThermostatModeTobasic(size_t channel, size_t value) {
if (value == 0x0)
return (0x0);
value = THERMOSTAT_MODE_HEAT;
while (value <= THERMOSTAT_MODE_FULL_POWER) {
if (_bitTestComponentId(channel, value) == true)
return (value);
value++;
static uint8_t __zuno_CCThermostatModeTobasicSet_any(uint32_t support_mode_mask, int8_t id_cmp, uint8_t id_default) {
int8_t id_find;

id_find = 0x0;
while (support_mode_mask != 0x0) {
if ((support_mode_mask & 0x1) != 0x0) {
if (id_cmp != id_find)
return (id_find);
}
support_mode_mask = support_mode_mask >> 0x1;
id_find++;
}
return (0x0);
return (id_default);
}

static uint8_t __zuno_CCThermostatModeTobasicSet_null(uint32_t support_mode_mask) {
int8_t id_null;
int8_t id_ff;

if ((id_null = _termostat_mode_basic_set(&_termostat_mode_basic_null[0x0], (sizeof(_termostat_mode_basic_null) / sizeof(_termostat_mode_basic_null[0x0])), support_mode_mask)) >= 0x0)
return (id_null);
id_ff = _termostat_mode_basic_set(&_termostat_mode_basic[0x0], (sizeof(_termostat_mode_basic) / sizeof(_termostat_mode_basic[0x0])), support_mode_mask);
return (__zuno_CCThermostatModeTobasicSet_any(support_mode_mask, id_ff, _termostat_mode_basic_null[0x0]));
}

static uint8_t __zuno_CCThermostatModeTobasicSet_ff(uint32_t support_mode_mask) {
int8_t id_null;
int8_t id_ff;

if ((id_ff = _termostat_mode_basic_set(&_termostat_mode_basic[0x0], (sizeof(_termostat_mode_basic) / sizeof(_termostat_mode_basic[0x0])), support_mode_mask)) >= 0x0)
return (id_ff);
id_null = __zuno_CCThermostatModeTobasicSet_null(support_mode_mask);
return (__zuno_CCThermostatModeTobasicSet_any(support_mode_mask, id_null, _termostat_mode_basic[0x0]));
}

uint8_t __zuno_CCThermostatModeTobasicSet(uint8_t channel, uint8_t value) {
uint32_t support_mode_mask;

support_mode_mask = _get_termostat_mode_support_mask(channel);
if (value == 0x00)
return (__zuno_CCThermostatModeTobasicSet_null(support_mode_mask));
return (__zuno_CCThermostatModeTobasicSet_ff(support_mode_mask));
}

uint8_t __zuno_CCThermostatModeTobasicGet(size_t channel) {
uint8_t value;
uint32_t support_mode_mask;

value = zuno_universalGetter1P(channel);
support_mode_mask = _get_termostat_mode_support_mask(channel);
if (__zuno_CCThermostatModeTobasicSet_null(support_mode_mask) == value)
return (0x0);
if (__zuno_CCThermostatModeTobasicSet_ff(support_mode_mask) == value)
return (0xFF);
return (0xFE);
}

static int _set_mode(size_t channel, const ZwThermostatModeSetFrame_t *cmd) {
size_t componentId;
uint8_t componentId;

componentId = cmd->v2.level & THERMOSTAT_MASK_4_BIT;
if (_bitTestComponentId(channel, componentId) == false)
if (_termostat_mode_is_valid(channel, componentId) == false)
return (ZUNO_COMMAND_BLOCKED_FAILL);
zuno_universalSetter1P(channel, componentId);
zunoSendReport(channel + 1);
Expand Down Expand Up @@ -114,16 +195,17 @@ int zuno_CCThermostatModeHandler(uint8_t channel, const ZUNOCommandCmd_t *cmd, Z
}

static int _supported_report_setpoint(uint8_t channel, ZUNOCommandPacketReport_t *frame_report) {//Processed to get the value of the thermostatmode components
ZwThermostatSetpointSupportedReportFrame_t *lp;
uint8_t sub_type;
ZwThermostatSetpointSupportedReportFrame_t *report;
uint32_t support_mode_mask;
uint8_t len;

lp = (ZwThermostatSetpointSupportedReportFrame_t *)frame_report->info.packet.cmd;
sub_type = ZUNO_CFG_CHANNEL(channel).sub_type;//It contains a bitmask of thermostat
support_mode_mask = _get_termostat_set_point_support_mask_interpretation_a(channel);
report = (ZwThermostatSetpointSupportedReportFrame_t *)frame_report->info.packet.cmd;
// lp->byte2.cmdClass = COMMAND_CLASS_THERMOSTAT_SETPOINT; set in - fillOutgoingPacket
// lp->byte2.cmd = THERMOSTAT_SETPOINT_SUPPORTED_REPORT; set in - fillOutgoingPacket
lp->byte2.bitMask1 = sub_type & 0x7E;
lp->byte2.bitMask2 = (sub_type >> 7) << 3;//This field MUST be encoded according to Table 142, interpretation A:
frame_report->info.packet.len = sizeof(lp->byte2);
len = ((((sizeof(support_mode_mask) * 0x8) - __builtin_clz(support_mode_mask)) >> 0x3) + 0x1);
memcpy(&report->bitMask[0x0], &support_mode_mask, len);
frame_report->info.packet.len = sizeof(report[0x0]) + len;
return (ZUNO_COMMAND_ANSWERED);
}

Expand Down Expand Up @@ -168,11 +250,11 @@ static int _setpoint_get(size_t channel, const ZwThermostatSetpointGetFrame_t *
componentId = componentId & THERMOSTAT_MASK_4_BIT;//Setpoint Type (4 bits)
report->cmdClass = COMMAND_CLASS_THERMOSTAT_SETPOINT;
report->cmd = THERMOSTAT_SETPOINT_REPORT;
if (_bitTestComponentId(channel, componentId) == true) {
if (_get_termostat_set_point_is_valid(channel, componentId) == true) {
report->level = componentId;
report->level2 = THERMOSTAT_SETPOINT_PARAMETR(THERMOSTAT_SETPOINT_SIZE, THERMOSTAT_SETPOINT_SCALE(channel), THERMOSTAT_SETPOINT_PRECISION);
out = zuno_universalGetter2P(channel, componentId);
out = _limit_setpoint(ZUNO_CFG_CHANNEL(channel).params[0], out);
out = _limit_setpoint(_get_compresed_combi_value(channel), out);
report->value[0x0] = (uint8_t)(out >> (sizeof(out) * 8 / 2));
report->value[0x1] = (uint8_t)(out & 0xFF);
count = THERMOSTAT_SETPOINT_SIZE;
Expand All @@ -189,18 +271,15 @@ static int _setpoint_get(size_t channel, const ZwThermostatSetpointGetFrame_t *

static int _set_setpoint(uint8_t channel, const ZUNOCommandCmd_t *cmd) {
ZwThermostatSetpointSetFrame_t *lp;
size_t sub_type;
uint16_t value;

lp = (ZwThermostatSetpointSetFrame_t *)cmd->cmd;
sub_type = ZUNO_CFG_CHANNEL(channel).sub_type;//It contains a bitmask of thermostat
sub_type = (sub_type & 0x7E) | ((sub_type >> 7) << 3);//This field MUST be encoded according to Table 142, interpretation A:
if ((sub_type & (0x1 << (lp->byte1.level & THERMOSTAT_SETPOINT_SET_LEVEL_SETPOINT_TYPE_MASK))) == 0x0)
if (_get_termostat_set_point_is_valid(channel, (lp->byte1.level & THERMOSTAT_SETPOINT_SET_LEVEL_SETPOINT_TYPE_MASK)) == false)
return (ZUNO_COMMAND_BLOCKED_FAILL);
if ((lp->byte1.level2 & (THERMOSTAT_SETPOINT_SET_LEVEL2_SIZE_MASK | THERMOSTAT_SETPOINT_SET_LEVEL2_SCALE_MASK)) != (THERMOSTAT_SETPOINT_SIZE | (THERMOSTAT_SETPOINT_SCALE(channel) << THERMOSTAT_SETPOINT_SET_LEVEL2_SCALE_SHIFT)))
return (ZUNO_COMMAND_BLOCKED_FAILL);
value = lp->byte2.value2 | (lp->byte2.value1 << (sizeof(value) * 8 / 2));
value =_limit_setpoint(ZUNO_CFG_CHANNEL(channel).params[0], value);
value =_limit_setpoint(_get_compresed_combi_value(channel), value);
zuno_universalSetter2P(channel, lp->byte2.level & THERMOSTAT_MASK_4_BIT, value);
return (ZUNO_COMMAND_PROCESSED);
}
Expand All @@ -218,8 +297,8 @@ static int _setpoint_capabilities_get(size_t channel, const ZwThermostatSetpoint
data = &report->data[0x0];
int16_t up_limit;
int16_t down_limit;
_get_limits_setpoint(ZUNO_CFG_CHANNEL(channel).params[0], down_limit, up_limit);
if (_bitTestComponentId(channel, componentId) == true) {
_get_limits_setpoint(_get_compresed_combi_value(channel), down_limit, up_limit);
if (_get_termostat_set_point_is_valid(channel, componentId) == true) {
report->properties1 = componentId;
data[0] = THERMOSTAT_SETPOINT_PARAMETR(THERMOSTAT_SETPOINT_SIZE, THERMOSTAT_SETPOINT_SCALE(channel), THERMOSTAT_SETPOINT_PRECISION);
data[1] = down_limit >> 8;
Expand Down
Loading

0 comments on commit a3fb8b4

Please sign in to comment.