Whole home cold air scent diffuser automation is possible without crappy apps!

OK so here’s a little guide based on how I did it…

I did it using an Android phone, so if you use iOS, adjust accordingly.
My HA installation is in french, so it’s possible that I’m a bit off when I name things in HA settings and whatnot, but you’ll understand what I mean.

You need a compatible diffuser that uses the Aroma-Link app.
I’m using this one that I paid too much for on Amazon because it’s just a rebranded chinese model that gets rebranded under many different names. Different names, different prices.

Once your diffuser is added in the app, you can proceed…

Getting your Aroma-Link Access Token, User ID and Device ID

To get the access_token, deviceId and userId, I used this app: PCAPdroid.
Do the following in that order. Note that it doesn’t matter much how you navigate in the Aroma Link app while capturing packets, but the way I did it gave me the 3 things I needed right away.

  • Open the Aroma Link app and go to the page where you can see your diffuser and its status
  • Open PCAPdroid and select the Aroma-Link app under “Target apps”. For the extraction, you can leave it as is, you don’t need it.
  • Press the PLAY button (top right) and select “Live capture
    – Go to the Aroma-Link app and click on your diffuser
    – Wait for the page to load
    – Press back
    – Press back again
    – Click on the “Me” icon
  • Go back to the PCAPdroid app and press que STOP button.
  • Go to the “CONNEXIONS” tab and you should see a few entries. One will have your userID and another one will have your deviceID. They will both have your access token under the HTTP or PAYLOAD tabs.

access_token should have about 232 characters
userId is a 5-digit number
deviceId is a 6-digit number

HA side of things

Now, in HA, there are two REST commands that need to be executed. One is to turn the diffuser ON or OFF, and the other one sets a schedule in the Aroma-Link app.

When the diffuser turns on, it automatically diffuses and it uses the number of seconds set in the scheduler. This is why you will need a command to change the scheduler.

You want HA to control how long the diffuser stays off and for how long it diffuses, not the diffuser built-in scheduler.
To do that, you want a script that will set the scheduler first, then turn the diffuser on, wait X number of seconds depending on how long you want the diffuser to work, then turn the diffuser off.

HA | Adding the REST commands to configuration.yaml

You need to edit configuration.yaml. For this, you need an editor. I use Studio Code Server.
After editing that file, you NEED to go to Developer Tools > YAML tab and check your configuration for errors. Don’t restart HA if it gives you errors. Fix it in configuration.yaml first and make sure it passes the config check. Always have a backup before doing anything.

Don’t forget to change YOUR_DEVICE_ID for your deviceId, YOUR_USER_ID for your userId and YOUR_ACCESS_TOKEN for your access_token.

COMMAND #1: ON AND OFF

This is the first command you would copy and paste in configuration.yaml, but don’t do it just yet:

rest_command:
  diffuser_on
    url: https://www.aroma-link.com/v1/app/data/newSwitch?deviceId=YOUR_DEVICE_ID&userId=YOUR_USER_ID&onOff=1
    method: POST
    headers:
      access_token: "YOUR_ACCESS_TOKEN"
      payload: ""

This command will turn the diffuser on because of the onOff=1 part.
To turn it off, it needs to be onOff=0 and of course you would want to change the name of the command to diffuser_off instead of diffuser_on, for instance.

You have two options here. You either have a REST command to turn on and another one to turn off, OR, you have only one with the option to change the onOff value dynamically, from the dashboard for instance, like I did.

So for option #1, you have to add this to configuration.yaml:

rest_command:
  diffuser_on
    url: https://www.aroma-link.com/v1/app/data/newSwitch?deviceId=YOUR_DEVICE_ID&userId=YOUR_USER_ID&onOff=1
    method: POST
    headers:
      access_token: "YOUR_ACCESS_TOKEN"
      payload: ""

  diffuser_off
    url: https://www.aroma-link.com/v1/app/data/newSwitch?deviceId=YOUR_DEVICE_ID&userId=YOUR_USER_ID&onOff=0
    method: POST
    headers:
      access_token: "YOUR_ACCESS_TOKEN"
      payload: ""

For option #2, which I recommand, you have to add this to configuration.yaml:

rest_command:
  diffuser_on_or_off:
    url: https://www.aroma-link.com/v1/app/data/newSwitch?deviceId=YOUR_DEVICE_ID&userId=YOUR_DEVICE_ID&onOff={{diffuser_want_on_or_off}}
    method: POST
    headers:
      access_token: "YOUR_ACCESS_TOKEN"
      payload: ""

Again, don’t forget to check your configuration under Developer Tools, then restart HA if everything is OK. After that, your command(s) will be available.

Say you went with option #2 to turn on or off the diffuser. You can test your command(s) under Developer Tools > Services by calling a service > RESTful Command: diffuser_on_or_off

Service data:

diffuser_want_on_or_off: 1

If sucessful, it should return this:

content:
  code: 200
  msg: OK
status: 200

The Aroma-Link app is pretty bad, so if you want to see changes, you need to close the app, then re-open it. Only then you should see that the diffuser is ON. Again, the icons are pretty bad too, but you will notice that the ON/OFF card at the bottom is somewhat enlighted.

Now that it’s working, you can create the script that will turn the diffuser on or off. Note that it’s just a really basic example with a static wait time. You would want to go a bit more advanced and mathematically adjust the wait time depending on how long you have set the number of seconds it diffuses (see next step below) through a number helper for instance, and have diffuser_want_on_or_off also being adjusted dynamically.

So here’s a basic example in YAML

alias: Turn diffuser on then off
sequence:
  - service: rest_command.diffuser_on_or_off
    data:
      diffuser_want_on_or_off: 1
  - delay:
      hours: 0
      minutes: 0
      seconds: 40
      milliseconds: 0
  - service: rest_command.diffuser_on_or_off
    data:
      diffuser_want_on_or_off: 0
mode: single
icon: mdi:spray

COMMAND #2: ADJUST SCHEDULER

This one’s a bit more complex, but there really is just one thing to play with and it’s the diffuse time in seconds.
This goes along with “option #2” for the on and off command: we want to be able to adjust the number of seconds dynamically, so we won’t hardcode a number in the command.

  diffuser_set_scheduler:
    url: https://www.aroma-link.com/v1/app/data/workSetApp
    method: POST
    headers:
      access_token: "YOUR_ACCESS_TOKEN"
      Content-Type: "application/json"
    payload: >
      {
        "deviceId": YOUR_DEVICE_ID, 
        "userId": YOUR_USER_ID,
        "week": [0, 1, 2, 3, 4, 5, 6], 
        "workTimeList": [
          { "consistenceLevel": 1, "enabled": 1, "endTime": "23:59", "pauseDuration": 900, "startTime": "00:00", "workDuration": {{diffuser_number_of_seconds_on}} },
          { "consistenceLevel": 1, "enabled": 0, "endTime": "00:00", "pauseDuration": 900, "startTime": "00:00", "workDuration": 10 }, 
          { "consistenceLevel": 1, "enabled": 0, "endTime": "00:00", "pauseDuration": 900, "startTime": "00:00", "workDuration": 10 }, 
          { "consistenceLevel": 1, "enabled": 0, "endTime": "00:00", "pauseDuration": 900, "startTime": "00:00", "workDuration": 10 }, 
          { "consistenceLevel": 1, "enabled": 0, "endTime": "00:00", "pauseDuration": 900, "startTime": "00:00", "workDuration": 10 }
        ]
      }

Noticed that this line is missing compared to the on and off command: rest_command:
It’s because you already have it for your on and off command. You don’t want it twice. So just paste this in configuration.yaml right under your other command.
Check your configuration for errors, if everything is OK, restart HA.

Now you can create an input number helper for the number of seconds it diffuses. I suggest you set a minimum value of 2 and a maximum of 30. Set units to seconds.
Let say its entity is input_number.diffuser_set_diffuse_time

You could test the command like we did for the on/off one, but lets just jump straight to the script, and once again, it’s a pretty basic one.

alias: Turn diffuser on then off with adjusted diffuse time
sequence:
  - service: rest_command.diffuser_set_scheduler
    data:
      diffuser_number_of_seconds_on: "{{ states('input_number.diffuser_set_diffuse_time') }}"
    enabled: true
  - delay:
      hours: 0
      minutes: 0
      seconds: 2
      milliseconds: 0
  - service: rest_command.diffuser_on_or_off
    data:
      diffuser_want_on_or_off: 1
    enabled: true
  - delay:
      hours: 0
      minutes: 0
      seconds: 40
      milliseconds: 0
    enabled: true
  - service: rest_command.diffuser_on_or_off
    data:
      diffuser_want_on_or_off: 0
    enabled: true
mode: single
icon: mdi:spray

You now have a script that will get the number of seconds from your input number helper and set it in your diffuser’s built-in scheduler, wait 2 seconds, turn the diffuser on, then the diffuser will automatically diffuse for the number of seconds you have just set, wait 40 seconds while it’s doing its thing, turn the diffuser off.

And again, you can change the 40 seconds delay for a dynamic or static number that will exceed your diffuse time. You don’t want the diffuser to turn off before it finishes diffusing.

You can now run your script whenever you want. Have automations run it, run it from the dashboard, etc.

@cloudbr34k

2 Likes

Wow! Thank you! will give this a crack today!

Hey mate
SO i managed to get Token, UserID but im not getting Device ID mp matter where i go in thje app. I even recorded logging into the app etc? Any ideas?
Maybe this

GET /v1/app/user/xxxxxx?language=EN HTTP/1.1
Host: www.aroma-link.com
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/4.5.0
access_token: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
version: 406
HTTP/1.1 200 
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Sun, 05 May 2024 10:30:53 GMT

{"code":200,"msg":"OK","data":{"userId":xxxxx,"userName":"xxxxxxxxxxxxx","name":"[email protected]","email":null,"mobile":"","status":1,"userIdCreate":null,"gmtCreate":1714450335000,"gmtModified":1714450366000,"userseltimezone":"AEST","continentId":-1,"countryId":-1,"areaId":-1,"continentName":null,"countryName":null,"areaName":null,"picId":null,"avatarUrl":null,"appId"

This is what i have

great thread, hope to see more on maybe even hacking/building an ESPhome with better controls. I have the jCloud wifi and chose to just do the smartSwitch route:

The program settings: 45s / 120s

automation: When Nest turns to “cooling” turn on ScentPlug
When Nest turns to “idle” turn off ScentPlug

When in idle, every 10 minutes, turn on A/C fan and run for 15 mins (turning on ScentPlug)

This works well for now but would like cleaner and more precise controls

Are you using the same app as I did?

yeha mate Aroma-link app

I meant the one to capture the packets: PCAPdroid

yeah same one as well. I tried your steps as well as jsut about every other step, just weird

have you done anything else with the aroma-link app?
What phone are you using?

No. I did everything mentionned in my guide. If you see your diffuser in the Aroma-Link app, then it must have a device ID.
Do you connect to it over Wifi or Bluetooth? Just make sure to use Wifi.

Oh! wifi! i been using gluettoth as its a bluetooth device

Thank you so much for such wonderful manual!
Can you please advise if there is any chance to get the status (i.e. make the switch)?

Is there a way to get the id with an iphone?

I think I got this working! One twist is that I have the device in an IoT VLAN with internet access blocked off, and it seems this definitely requires the diffuser to have internet access (was hoping it would somehow connect locally). On that same thought, does anyone know how to accomplish the same thing but using its Bluetooth connection?

Ideally someone smarter than me develops a basic integration that can be installed in Home Assistant but beggars can’t be choosers!

Thank you to everyone on this thread!! Had this up and running in minutes… One little word of advice if you get the ubiquitous Jcloud version / 300ML and the beep is VERY VERY loud, just open it up (6 screws) use a little hot glue on the opening of the “buzzer” makes it super quiet…

I have a diffuser like this but it is not an HVAC model, it is a small model for a simple home. It also works with the Aroma-Link app. But it only connects via Bluetooth. Is there a chance I can integrate an ESP32 chip into this machine? If anyone can help, I can disassemble it and share pictures.

Hi, I interated my aroma diffuser exactly as described here. It was working like a charm last few weeks.
But it stopped yesterday. I’ve seen that in scripts, api calls are through httpS, whereas app sends without encryption. After changing to HTTP it started once again.

HTTPS was better, but I suppose it was switched off in api provider side.

It looks like their SSL certificate expired @andzuk.

I couldn’t get the POST requests detailed by @fauxPalindrome to work over http or https. I got an unauthorized / token expired error from the server. When I intercepted packets from the app I got a different content-type with more info in the payload. The below worked for me, for example:

curl -X POST \
-H "Content-Type: multipart/form-data; boundary=&" \
-H "access_token: [TOKEN]" \
-d $'--&\r\nContent-Disposition: form-data; name=\"deviceId\"\r\n\r\n[DEVICEID]\r\n--&\r\nContent-Disposition: form-data; name=\"onOff\"\r\n\r\n[1/0]\r\n--&\r\nContent-Disposition: form-data; name=\"userId\"\r\n\r\n[USERID]\r\n--&--' \
"http://www.aroma-link.com/v1/app/data/newSwitch"

And because I gave up trying to configure that for rest_command in YAML, I put it in a script and used shell_command instead.

Side note: if anyone has this exact device (the box on mine says it’s the PRO by Ouwave but it looks the same as fauxPalindrome’s), please shoot me a DM. I can’t get it to work and the manufacturer isn’t being helpful. No oil is diffused - should there be airflow from the silicon gasket on the inside of the bottle compartment?

Can some share the link to the one your purchased please. One that works with the Aroma App?

I have similar looking diffuser under different brand name. There should be airflow indeed from the silicon gasket, the unit is pushing the air into the cap assembly of the fragrance oil bottle during operation.