Project tutorial

Hygge Home - Alexa Smart Bath © CC BY-NC-SA

Using Alexa and Arduino to instil a sense of Hygge upon your arrival home. Fully functioning Alexa controlled smart bath.

  • 24 respects

Components and supplies

Arduino Yun Mini
Amazon echo dot
Amazon Alexa Echo Dot
11026 02
Jumper wires (generic)
1/2 Inch 12V Electric Solenoid Valve for Water
Flexible Tap Connector 15mm x ½" x 300mm
Equal Tee 15mm x 15mm x 15mm
Male Coupler 15mm x ½"
Female Coupler 15mm x ½"
15mm Copper Pipe
3 Hole Bath Faucet Tap
13268 01
SparkFun Snappable Protoboard
Mfr 25frf52 10k sml
Resistor 10k ohm

Necessary tools and machines

Pipe Cutter
09507 01
Soldering iron (generic)
Adjustable Wrench

Apps and online services

About this project



‘It is late December, the days are short, the nights long. Your journey home from work is a bitter, cold and dark one. You long for nothing more than to arrive at a home alive with the flicker of candle light, where a hot drink and warm bath await you. Instead, when you open the door, the house is eerily quiet, rooms filled with the winter darkness.’


Hygge (pronounced hue-guh) is a Danish concept used to describe a distinct feeling of cosiness and warmth, it’s extremely prevalent in Danish culture and has recently spread across many homes around the globe. Hygge is something I've come a lot recently and no matter where you look you just can't get away from this latest craze. See for yourself:

My project utilises an Arduino controlled Smart Bath to instil a sense of Hygge, creating a homely and warming atmosphere upon your arrival home via Alexa voice integration.

The main control unit for my system is the Arduino Yun Mini, this is used to control the Solenoid valves which control the flow of water.

As you can see in the video above I created a fully functioning prototype of the bath, using a hose to supply pressurised water to the cold side. Not only did this enable me to test the design but I hope it will clearly illustrate how everything operates in terms of the plumbing involved. The bath can be operated both manually or via Alexa just in case the internet ever cuts out and you wanted a bath. The bath fills up on a timer programmed within the Arduino Code, there's also a reset switch which makes sure you can't accidentally turn it on twice and overflow the bath.

I created and used an Alexa routine for the video which meant when I say "Alexa, I'm home" the bath turns on and I receive a welcome home greeting. Below is a video to setup your own:

Alexa Routine Setup

Disclaimer: If you choose to follow this tutorial to create your own smart device you do so at your own risk. I’m neither a trained electrician nor plumber and therefore would not recommend installing these devices in your home without professional assistance. Dealing with mains power is extremely dangerous and can result in major injuries or even death. There are also regulations around the use of powered devices in a bathroom, again I would not recommend installing the bath control without professional assistance as a single code error could lead to a flooded bathroom.

Design Challenges

Before embarking on this project I decided to take a step back and make note of the key challenges I was going to have to overcome to make this idea a reality. I knew it wasn't going to be easy but I hoped this would help me keep on top of things:

  • Creating a leak free system, having never attempted any plumbing before I was hesitant as to whether or not this would even be water tight. But by following best practices for plumbing this turned out to be one of the easier challenges to overcome.
  • Coding the Skill. Having never stepped foot into the realm of Alexa skills I knew this was going to be the hardest part. Luckily the guides provided by amazon made this a relatively smooth process and I ended up making a few tutorial type skills before I was confident enough to produce my own.
  • Arduino Yun Coding. While I had worked with Arduino before I had never used an Arduino Yun, which although built upon the same software the added linux platform isn't something I had come across before.
  • Documenting the process. Having never written any sort of tutorial for my work the write up of the whole process and design was an intimidating one.

The Skill

You can find the published Alexa skill here or search for "Hygge Home": this gives you an example of what the skill will look like however you won't be able to operate the device as I can't have strangers controlling my taps...

How It Works

Below is an interaction diagram and explanation which shows the sequence of events that occur when I say a command such as “Alexa, Turn on the bath”. I’ll be going through each of these steps in this tutorial so you can create your very own Alexa smart device!

1. The Alexa home skill I made and published named "Hygge Home" allows me to control the Arduino based device with On/Off functionality. This is what you install on the Alexa app to control your device.

2. AWS Lambda receives the commands from the Alexa skill and sends the relevant data to update the AWS IoT Thing Shadow.

3. AWS IoT hosts a virtual version of the device known as the “Thing Shadow” this updates with the desired state of the device such as “Turn On” or “Turn Off”.

4. The Arduino Yun Mini monitors the MQTT feed of the thing shadow and reacts to the required command by controlling the mosfets that correspond to either the hot or cold solenoid valve.

Build Tutorial

I will be going through each stage of the process step by step with “checkpoints” along the way so you can check your progress and make sure it’s working as expected before moving on. This should help to iron out any issues early on and make things run as smoothly as possible. The tutorial is focused on the smart bath control but could be adapted to many other devices. If you have any questions please don’t hesitate to ask and I will try my best to help.

The Alexa Skill

We will begin by creating the Alexa skill, the Alexa documentation proved to be an invaluable source of information with regards to this and I strongly suggest reading through the getting started pages prior to creating your own.

1. Developer Account

In order to access the Alexa console, you will first need to create a developer account via this link

2. Alexa Skill Dashboard

Next navigate to the Alexa dashboard and click getting started on the left-hand side under “Alexa Skills Kit”

3. Setup – Skill Information

On the next page, you want to click the “Add New Skill” button which will bring you to the following page.

I’ve highlighted in red the key points which are as follows:

  • Skills Type: Smart Home Skill API - This is used to provide basic On/Off functionality and is the easiest type to get started with.
  • Language: English(U.K)
  • Name: Hygge - For this tutorial I suggest using the same name first time round then changing the name in the future once things are operational and you understand how each section links together.
  • Payload Version: v3 (Preferred) - At the time of writing this is the latest version but is likely to change in the future, the changes will need to be made to the Lambda function accordingly.


3a. Setup –Interaction Model

Not needed as we are using the Smart Home Skill API which takes care of this for us. However, you need to note down your Application ID. Found below the name of your skill in the top left and looks something like: amzn1.ask.skill.xxxxxxxxx-xxxxxxxx-xxxxxxxxxx

4. Setup –Configuration

It’s in this section where you provide the bulk of the back end information the skill requires, we can fill in most of this however the AWS Lambda Endpoint will have to remain blank for now. This section also requires us to setup some authorisation details which will generate the required security information for us to use.

4a – Security Profile

We need some extra details to be able to authorise our skill, in this section we will setup the appropriate security profile and note the information we need.

First navigate to select “Create a New Security Profile

Then fill in the required information and hit “Next

Now navigate to the security profile page and select the profile you just created. From here make note of your Client ID and Client Secret

4b - Web Settings

Click the “Web Settings” tab then “Edit” and then copy in your Return URL.This can be found on your Alexa Skill configuration page about half way down.It will look something like this:

4c - Configuration

  • Scope: For this we just need to add the following: “profile:_user_id
  • Authorization Grant Type: “Auth Code Grant
  • Client Secret: Paste your client secret from step 4a here.

5. Test

Once that is saved you can now open the Alexa app on your preferred smart phone of choice and download and install your skill! It won’t have any functionality but it’s there and if you can successfully authenticate then it’s working.

AWS Lambda

That’s the skill done for now, hopefully you have the skill installed on your Alexa app. It’s now time to use AWS Lambda to add some device functionality.

1. Create Function

Head to and click the “Create Function” button in Orange. You will notice I’m using the “EU-West”region, I suggest keeping to this for the purpose of this tutorial and changing to suit your own region afterwards.

2. Setup Options

  • Author from Scratch
  • Name: HyggeHome
  • Runtime: Python2.7
  • Role: Create Custom Role -This will open a new window where you should select the following values:
  • IAM Role: Lambda_Basic_Execution
  • PolicyName: “Create New Policy” then edit the policy and paste in the following:

{ "Version": "2018-12-01", "Statement": [ {"Effect": "Allow", "Action": ["logs:CreateLogGroup", "logs:CreateLogStream","logs:PutLogEvents" ], "Resource":"arn:aws:logs:*:*:*" }, { "Effect": "Allow","Action": "iot:UpdateThingShadow", "Resource": "*"} ] }

Click “Create Function” Bottom Right

3. Link to Skill

On the left hand side, we need to select the trigger for the function. Select “Alexa Smart Home”

If you scroll down it will ask for Application Id, this can be found on your Alexa Skill developer console. Refer to step 3a.

You can also now copy your Lambda function endpoint into the Alexa skill configuration page.

4. Code

Once that is added if you scroll down you will get to the code editor. Simply remove any existing code and paste in the Lambda code found below and click save! We will replace the dummy information later to match your own devices, however for now make no changes to the code.

5. Test

The code you have copied in contains dummy data which will need to be replaced by your AWS IoT Thing data once setup. For now, If you search for devices on the Alexa App you should see the device. If this is correct then so far so good.


You should now have a functioning skill and lambda function. Now the next step is to create your virtual “Thing” via AWS IoT. The lambda function updates a virtual device which can then be mimicked by the Arduino via its mqtt feed.

First, we will setup the basic “Thing” then generate the required certificates for the Arduino. It’s important to keep the certificates saved and backed up as you only get one chance to do so.

1. Setup

Head to “”which should bring you to the following page, click “Create a Single Thing”.

1a. Thing Information

On the next page you just need to provide a name for your“Thing”, I’ll be using smart-bath. This is the name you’ll refer to when controlling your device, it’s a good idea to keep this consistent across the different stages for ease of use. Scroll down and click Next.

1b. Certificates

On this section we need to click “Create Certificate”

This will bring you to a page where you need to download and keep note of the following:

  • “A certificate for this thing”
  • Private Key
  • root CA

These keys are crucial to the Arduino communication with the Thing Shadow and this is the only chance you will have to note them down

Click “Activate

Then “Done

2. Policy

You should then be redirected to the Thing Dashboard and see the device you just registered. Next we need to create a permission policy for the monitoring. You can either head to Secure> Policy > Create on the left side or visit

Fill in the information as per the example below and click “Create

  • Name: HyggePolicy
  • Action: iot:*
  • Resource: *
  • Effect: Allow

3. Attach Policy

The last step is to head to the certificates section on the left hand side. Click the three small dots above your certificate and click “Attach Policy”.

If you click on the certificate you should now see both the Policy and Thing attached to it. The next step is to link this to the Lambda Function so we can update the Thing Shadow via Alexa.

4. Note Thing Information

Before we link the lambda function we need to make a note of a few things. Head to your Thing Dashboard and select the Thing you just created. On the left hand side select “Interact”. From this section note the following:

  • Rest API Endpoint:
  • Thing Name: smart-bath

5. Linking AWS Lambda and AWS IoT

Simply head back to your Lambda Function and replace the end point with the one you just noted down. Your thing name should still be "smart-bath" so there's no need to make changes for that.

First Test

You should now have your skill linked to the Alexa app on your smartphone, the skill is linked to the Lambda function and that function can update your AWS IoT Thing Shadow. If you open your thing and select the “Shadow” section you can then turn the device on and off via the app and see this reflected in the shadow document.

If everything is working okay and your Thing is updating accordingly then the main setup of Alexa is finished and it’s on to the Arduino section.

Arduino Setup

The last section is to setup the Arduino to monitor our Thing Shadow and respond accordingly. By stripping out the timing function and reset button this code could be adjusted to suit other devices such as plugs or lamps.

I’m using an Arduino Yun Mini, however the same process applies for the Arduino Yun. You just to need to make sure you have the correct board selected when it comes to uploading the sketch.

1. Arduino Yun Mini –Setup

You may already have done this step but for anyone working with a new board the process is very well outlined here : thanks to Hackster user @BenEagen for finding this guide.


The next step is to set up the SDK for the Arduino board. This is very well documented by Amazon here:

Make sure you use the certificates downloaded in AWS IoT – Step 1b. This will enable secure communication between your Arduino and Amazon services. Once you’ve gone through their guide you will end up at the shadow echo example. Once you’ve filled in your details on the “aws_iot_config.h” you are almost ready to go. It’s worth running the example sketch and opening the serial monitor to make sure you can connect successfully.

3. Smart Bath Sketch

The final step is to simply open the sketch provided below and upload!

The sketch is based on the shadow example given by Amazon. When there is a request to turn on the bath the hot water tap will turn on for the given time, followed by the cold water tap. Once the bath is full the sketch recognises this and will not turn on again until the reset button has been pressed. This is to stop any accidental bath overflows. You can also turn off the bath before its finished, again this will require a press of the reset button afterwards.


That’s all the software completed. If you attach an LED to pin 3 and pin 6 then a button to pin 8 you can test the whole setup. You’ll notice the LED on pin 3 will stay on longer than pin 6. You will need to run a bath manually and time how long each tap is on for to achieve a bath at the desired level and temperature.

Building The Smart Bath

As you can see from the photo below the majority of this is your standard bath tap plumbing and will vary depending on your taps and bathroom setup. It's key to have the spout and handles separate, as this allows you to add in the Solenoid Tee junction.

As every installation will be different (and I'm no plumber) the dimensions for each section of pipe will vary massively. I used compression pipe fittings for ease of use but soldered joints would work just as well. You will find a list of parts I used above, including the thread sizes needed for each solenoid.

It's important to use jointing compound on all pipe fittings and some PTFE tape on all threaded connections. I used a hose adapter to test the design under nominal house water pressure.

As i'm no expert on plumbing i recommend the following guide on how to correctly use compression fittings:

The solenoids I used have the following specification, it's important they're able to handle the pressure of a household water supply. Mains water pressure will differ from house to house, however mine sits at around 4 bar. Specification:

  • Size: Approx. 8.8 * 7.6 * 5cm/ 3.5 * 3 * 2 inch (L*W*H).
  • Current 250mA / Pressure: 0 - 0.5Mpa.
  • Valve Type: Diaphragm (Operated by Servo).
  • Operation Mode: Normally Closed.
  • Max Fluid Temperature: 95 Degrees Celsius.
  • Usage: water and low viscosity fluid.
  • Voltage: 12v
  • Thread size: 1/2 inch

Below is also a circuit diagram for the Arduino Yun Mini.

Thank you for taking the time to read this guide! If you have any suggestions on how it can be improved or have any questions then I'll be happy to hear it and try my best to answer them!


Arduino CodeC/C++
 * Copyright 2010-2016, Inc. or its affiliates. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 * or in the "license" file accompanying this file. This file is distributed
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.

// Bath Timers
#define hotThreshold 20 //How long hot tap will run
#define coldThreshold 10 //How long cold tap will run
// Bath Pins
#define hotPin 3  //Pin for hot pipe solenoid
#define coldPin 6 //Pin for cold pipe solenoid
#define button 8  //Pin for button input

#include <aws_iot_mqtt.h>
#include <aws_iot_version.h>
#include "aws_iot_config.h"
int hotTimer = 0;
int coldTimer = 0;
int bathState = 0;
int buttonState = 1;
String bath = "off";

aws_iot_mqtt_client myClient;
char JSON_buf[100];
int cnt = 0;
int rc = 1;
bool success_connect = false;

bool print_log(const char* src, int code) {
  bool ret = true;
  if(code == 0) {
    #ifdef AWS_IOT_DEBUG
      Serial.print(F("[LOG] command: "));
      Serial.println(F(" completed."));
    ret = true;
  else {
    #ifdef AWS_IOT_DEBUG
      Serial.print(F("[ERR] command: "));
      Serial.print(F(" code: "));
    ret = false;
  return ret;

void msg_callback_delta(char* src, unsigned int len, Message_status_t flag) {
  if(flag == STATUS_NORMAL) {
    // Get delta for light key
    print_log("getDeltaKeyValue", myClient.getDeltaValueByKey(src, "light", JSON_buf, 100));
    if (strcmp(JSON_buf, "on") == 0)
        bath = "on";
        bath = "off";
    String payload = "{\"state\":{\"reported\":";
    payload += "{\"light\":\"";
    payload += JSON_buf;
    payload += "\"}}}";
    payload.toCharArray(JSON_buf, 100);
    print_log("update thing shadow", myClient.shadow_update(AWS_IOT_MY_THING_NAME, JSON_buf, strlen(JSON_buf), NULL, 5));

void setup() {
  pinMode (hotPin, OUTPUT);
  pinMode (coldPin, OUTPUT);
  pinMode (button, INPUT_PULLUP);

  char curr_version[80];
  snprintf_P(curr_version, 80, PSTR("AWS IoT SDK Version(dev) %d.%d.%d-%s\n"), VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);

  if(print_log("setup", myClient.setup(AWS_IOT_CLIENT_ID))) {
      if(print_log("connect", myClient.connect())) {
        success_connect = true;
        print_log("shadow init", myClient.shadow_init(AWS_IOT_MY_THING_NAME));
        print_log("register thing shadow delta function", myClient.shadow_register_delta_func(AWS_IOT_MY_THING_NAME, msg_callback_delta));

void loop() {
// Bath Control
 Serial.print (bath);
 Serial.println ();
 if (bath ==  "on") {
  while (hotTimer < hotThreshold && bath == "on") { 
  hotTimer ++;
  digitalWrite (hotPin,HIGH);
  delay (800);
    if(myClient.yield()) {
    Serial.println("Yield failed.");
  Serial.print (hotTimer);
  Serial.println ();
 digitalWrite (hotPin, LOW);
  while (coldTimer < coldThreshold && bath == "on" && bathState == 0) { 
  coldTimer ++;
  digitalWrite (coldPin,HIGH);
  delay (800);
    if(myClient.yield()) {
    Serial.println("Yield failed.");
  Serial.print (coldTimer);
  Serial.println ();
 bathState = 1;       //Turn off bath and enter reset loop
 bath = "off";
 digitalWrite (hotPin, LOW);
 digitalWrite (coldPin, LOW);

 if (bath == "off") {
  delay (800);
      if(myClient.yield()) {
    Serial.println("Yield failed.");

 if (bathState == 1) {      //Bath is full, Wait for reset button push
  while (buttonState == 1) {
    buttonState = digitalRead (button);
    delay (10);
  bathState = 0;
  buttonState = 1;
    delay (800);
    if(myClient.yield()) {
    Serial.println("Yield failed.");
 delay (1000);
AWS Lambda CodePython
import logging
import time
import json
import uuid
import datetime

import boto3

client = boto3.client('iot-data')

def get_utc_timestamp(seconds=None):
    return time.strftime("%Y-%m-%dT%H:%M:%S.00Z", time.gmtime(seconds))

def bath_state(state):
    # Change topic, qos and payload
    response = client.update_thing_shadow(
        thingName = "smart-bath",  #YOUR THING NAME HERE
        payload = json.dumps({
            'state': {
                'desired': {
                    'bath': state

def get_uuid():
    return str(uuid.uuid4())
# Setup logger
logger = logging.getLogger()

def lambda_handler(event, context):"Received v3 directive!")
    if event['directive']['header']['name'] == "Discover":"Discover")
        response = handle_discovery(event)
        response = handle_control(event, context)"response" + json.dumps(response))  
    return response

def handle_discovery(event):

        response = {
                        "correlationToken": "12345692749237492",
                        "namespace": "Alexa.Discovery",
                        "name": "Discover.Response",
                        "payloadVersion": "3",
                        "messageId": event['directive']['header']['messageId']
                          "endpointId": "smart-bath", 
                          "endpoint": "", #AWS IOT THING ENDPOINT HERE
                          "manufacturerName": "JHoward",
                          "friendlyName": "Smart Bath",
                          "description": "The smart bath",
                          "displayCategories": ["SWITCH"],
                          "cookie": {
                            "key1": "arbitrary key/value pairs for skill to reference this endpoint.",
                          "capabilities": [
                              "type": "AlexaInterface",
                              "interface": "Alexa",
                              "version": "3"
                              "interface": "Alexa.PowerController",
                              "version": "3",
                              "type": "AlexaInterface",
                              "properties": {
                                "supported": [
                                    "name": "powerState"
                                "proactivelyReported": True,
                                "retrievable": True
        }"Response: " +json.dumps(response))
        return response

def handle_control(request, context):
    request_namespace = request["directive"]["header"]["namespace"]
    request_name = request["directive"]["header"]["name"]
    if request_namespace == "Alexa.PowerController":
        if request_name == "TurnOn":
            value = "ON"
            value = "OFF"
        response = {
            "context": {
                "properties": [
                        "namespace": "Alexa.PowerController",
                        "name": "powerState",
                        "value": value,
                        "timeOfSample": get_utc_timestamp(),
                        "uncertaintyInMilliseconds": 500
            "event": {
                "header": {
                    "namespace": "Alexa",
                    "name": "Response",
                    "payloadVersion": "3",
                    "messageId": get_uuid(),
                    "correlationToken": request["directive"]["header"]["correlationToken"]
                "endpoint": {
                    "scope": {
                        "type": "BearerToken",
                        "token": "access-token-from-Amazon"
                    "endpointId": request["directive"]["endpoint"]["endpointId"]
                "payload": {}
        return response




Similar projects you might like

Smart Pool: Alexa Controlled Pool Manager

Project tutorial by Benjamin Winiarski

  • 12 respects

Arduino Home Controller Activated by Alexa

Project tutorial by Jose Cruz

  • 17 respects

Alexa Smart Power Strip with Temperature

Project tutorial by Muhammad Afzal

  • 1 comment
  • 13 respects

Scent-terrific Smart Candle

Project tutorial by Darian Johnson

  • 37 respects

Wise Shower Driven by Alexa Skill

Project in progress by Virgilio Enrique Aray Arteaga

  • 1 comment
  • 10 respects

Arduino-Powered Smart Light (Works with Amazon Echo)

Project tutorial by Tinker Project

  • 51 respects
Add projectSign up / Login