Skip to content

Commit

Permalink
Implemented Matter temperature measurement accessory.
Browse files Browse the repository at this point in the history
Signed-off-by: Marcin Kajor <[email protected]>
  • Loading branch information
markaj-nordic committed Nov 2, 2022
1 parent 1e1bb74 commit bacb1c1
Show file tree
Hide file tree
Showing 16 changed files with 3,487 additions and 1,277 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
3 changes: 3 additions & 0 deletions src/app_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#define FUNCTION_BUTTON DK_BTN1
#define FUNCTION_BUTTON_MASK DK_BTN1_MSK

#define SENSOR_BUTTON DK_BTN4
#define SENSOR_BUTTON_MASK DK_BTN4_MSK

#define SYSTEM_STATE_LED DK_LED1
#define FACTORY_RESET_SIGNAL_LED DK_LED2

Expand Down
12 changes: 11 additions & 1 deletion src/app_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@

class LEDWidget;

enum class AppEventType : uint8_t { None = 0, Button, ButtonPushed, ButtonReleased, Timer, UpdateLedState };
enum class AppEventType : uint8_t {
None = 0,
Button,
ButtonPushed,
ButtonReleased,
Timer,
UpdateLedState,
StartMeas,
StopMeas,
FetchMeas
};

enum class FunctionEvent : uint8_t { NoneSelected = 0, FactoryReset };

Expand Down
100 changes: 97 additions & 3 deletions src/app_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include <lib/support/CodeUtils.h>
#include <system/SystemError.h>

#include <app-common/zap-generated/attributes/Accessors.h>
#include <app/clusters/on-off-server/on-off-server.h>

#ifdef CONFIG_CHIP_WIFI
#include <app/clusters/network-commissioning/network-commissioning.h>
#include <platform/nrfconnect/wifi/NrfWiFiDriver.h>
Expand All @@ -36,6 +39,8 @@
#include <zephyr/logging/log.h>
#include <zephyr/zephyr.h>

#include <zephyr/drivers/sensor.h>

LOG_MODULE_DECLARE(app, CONFIG_MATTER_LOG_LEVEL);

using namespace ::chip;
Expand All @@ -50,6 +55,7 @@ constexpr uint32_t kFactoryResetTriggerTimeout = 6000;

K_MSGQ_DEFINE(sAppEventQueue, sizeof(AppEvent), kAppEventQueueSize, alignof(AppEvent));
k_timer sFunctionTimer;
k_timer sSensorTimer;

LEDWidget sStatusLED;
#if NUMBER_OF_LEDS == 2
Expand All @@ -62,6 +68,10 @@ FactoryResetLEDsWrapper<3> sFactoryResetLEDs{ { FACTORY_RESET_SIGNAL_LED, FACTOR
bool sIsNetworkProvisioned = false;
bool sIsNetworkEnabled = false;
bool sHaveBLEConnections = false;
bool sSensorActive = false;

const struct device *sTemperatureSensor = DEVICE_DT_GET_ONE(nordic_nrf_temp);

} /* namespace */

namespace LedConsts
Expand Down Expand Up @@ -155,6 +165,17 @@ CHIP_ERROR AppTask::Init()
k_timer_init(&sFunctionTimer, &AppTask::FunctionTimerTimeoutCallback, nullptr);
k_timer_user_data_set(&sFunctionTimer, this);

k_timer_init(
&sSensorTimer,
[](k_timer *timer) {
AppEvent event;
event.Type = AppEventType::FetchMeas;
event.TimerEvent.Context = k_timer_user_data_get(timer);
event.Handler = UpdateTemperatureClusterState;
PostEvent(event);
},
nullptr);

/* Initialize CHIP server */
#if CONFIG_CHIP_FACTORY_DATA
ReturnErrorOnFailure(mFactoryDataProvider.Init());
Expand Down Expand Up @@ -209,12 +230,21 @@ void AppTask::ButtonEventHandler(uint32_t buttonState, uint32_t hasChanged)

if (FUNCTION_BUTTON_MASK & hasChanged) {
button_event.ButtonEvent.PinNo = FUNCTION_BUTTON;
button_event.ButtonEvent.Action =
static_cast<uint8_t>((FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed :
AppEventType::ButtonReleased);
button_event.ButtonEvent.Action = static_cast<uint8_t>(
(FUNCTION_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed :
AppEventType::ButtonReleased);
button_event.Handler = FunctionHandler;
PostEvent(button_event);
}

if (SENSOR_BUTTON_MASK & hasChanged) {
button_event.ButtonEvent.PinNo = SENSOR_BUTTON;
button_event.ButtonEvent.Action = static_cast<uint8_t>(
(SENSOR_BUTTON_MASK & buttonState) ? AppEventType::ButtonPushed :
AppEventType::ButtonReleased);
button_event.Handler = ControlSensorHandler;
PostEvent(button_event);
}
}

void AppTask::FunctionTimerTimeoutCallback(k_timer *timer)
Expand Down Expand Up @@ -356,3 +386,67 @@ void AppTask::DispatchEvent(const AppEvent &event)
LOG_INF("Event received with no handler. Dropping event.");
}
}

void AppTask::UpdateTemperatureClusterState(const AppEvent &)
{
static constexpr int16_t kTemperatureMeasurementAttributeMaxValue = 0x7fff;
static constexpr int16_t kTemperatureMeasurementAttributeMinValue = 0x954d;
static constexpr int16_t kTemperatureMeasurementAttributeInvalidValue = 0x8000;
static constexpr uint8_t kTemperatureMeasurementEndpointId = 1;

struct sensor_value sTemperature;
EmberAfStatus status;
int err = sensor_sample_fetch(sTemperatureSensor);
if (!err) {
err = sensor_channel_get(sTemperatureSensor, SENSOR_CHAN_DIE_TEMP, &sTemperature);
if (!err) {
int16_t newValue = static_cast<int16_t>(sTemperature.val1 * 100 +
sTemperature.val2 / 10000);

if (newValue > kTemperatureMeasurementAttributeMaxValue ||
newValue < kTemperatureMeasurementAttributeMinValue) {
/* Read value exceeds permitted limits, so assign invalid value code to it. */
newValue = kTemperatureMeasurementAttributeInvalidValue;
}

LOG_INF("Current temperature: %d", newValue);

status = Clusters::TemperatureMeasurement::Attributes::MeasuredValue::Set(
kTemperatureMeasurementEndpointId, newValue);
if (status != EMBER_ZCL_STATUS_SUCCESS) {
LOG_ERR("Updating temperature measurement failed %x", status);
}
} else {
LOG_ERR("Getting temperature measurement data from sensor failed with: %d",
err);
}

} else {
LOG_ERR("Fetching data from temperature sensor failed with: %d", err);
}
}

void AppTask::ControlSensorHandler(const AppEvent &event)
{
if (event.ButtonEvent.Action == static_cast<uint8_t>(AppEventType::ButtonPushed)) {
sSensorActive = !sSensorActive;
if (sSensorActive) {
ChipLogDetail(DeviceLayer, "Starting timer");
k_timer_start(&sSensorTimer, K_SECONDS(2), K_SECONDS(2));
} else {
ChipLogDetail(DeviceLayer, "Stopping timer");
k_timer_stop(&sSensorTimer);
}

DeviceLayer::SystemLayer().ScheduleLambda([] {
// write the new on/off value
if (EMBER_ZCL_STATUS_SUCCESS !=
OnOffServer::Instance().setOnOffValue(1, sSensorActive, false)) {
ChipLogError(DeviceLayer, "Could not update the OnOff cluster");
} else {
ChipLogDetail(DeviceLayer, "Set OnOff cluster with value: %d",
sSensorActive);
}
});
}
}
7 changes: 5 additions & 2 deletions src/app_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
struct k_timer;

class AppTask {
public:
public:
static AppTask &Instance()
{
static AppTask sAppTask;
Expand All @@ -29,7 +29,7 @@ class AppTask {

static void PostEvent(const AppEvent &event);

private:
private:
CHIP_ERROR Init();

void CancelTimer();
Expand All @@ -45,6 +45,9 @@ class AppTask {
static void LEDStateUpdateHandler(LEDWidget &ledWidget);
static void FunctionTimerTimeoutCallback(k_timer *timer);
static void UpdateStatusLED();
static void UpdateTemperatureClusterState(const AppEvent &event);
static void SensorFetchMeasurement();
static void ControlSensorHandler(const AppEvent &event);

FunctionEvent mFunction = FunctionEvent::NoneSelected;
bool mFunctionTimerActive = false;
Expand Down
Loading

0 comments on commit bacb1c1

Please sign in to comment.