Aeotec wallmote quad zw130

Param 9 is the start point. Param 10 is the stop point. If you swipe upward, param 9 is lower than param 10, allowing you to know that it was an upward swipe. If you swipe down, 9 is larger. The numbers themselves probably correspond to the points on the touch-sensitive surface, which opens up swipes between the corners as well as up/down. Sideways swipes don’t appear to work.

Are these values accessible from within HA?

Also, for those having difficulty with the swipe, it’s…touchy. If you start the swipe with too much force, it shows up as a tap. One thing you can try is to lay your finger against the wallmote for a fraction of a second before moving it. Not long enough to register a hold, though. I have my wallmote laying on my desk for testing, and the sound of the vibration is different between swipe and tap.

How did you get swipe to work? I just bought one these and got group association tap to work pretty quickly (woot!), but haven’t had any luck with swipe group association and don’t see a solution in this thread.

i don’t have it working in any automation; i just understand what it’s sending in param 9 and 10 and can see those in the OZW logfile. as far as i can tell there’s nothing within HA that can effectively intercept and act on these parameters.

once i’m done moving all my automations from HA into NodeRED i’ll see if there’s any way to pull this directly from OZW and extract the params within NodeRED.

1 Like

Hi.
I’m interested in how you did this. Can you post your code?
bb

Sorry it took me a while to get back to you.

In configuration.yaml:

input_boolean:
  button_tap:
name: Quadmote button tap
icon: mdi:toggle-switch

Then create an automation rule to trigger the timer:

#id must be unique in your environment
- id: '1534001400878'
  alias: Wallmote tap timer
  trigger:
  - event_data:
  entity_id: zwave.aeotec_zw130_wallmote_quad
  scene_data: 0
  scene_id: 1
event_type: zwave.scene_activated
platform: event
  - event_data:
  entity_id: zwave.aeotec_zw130_wallmote_quad
  scene_data: 0
  scene_id: 2
event_type: zwave.scene_activated
platform: event
  - event_data:
  entity_id: zwave.aeotec_zw130_wallmote_quad
  scene_data: 0
  scene_id: 3
event_type: zwave.scene_activated
platform: event
  - event_data:
  entity_id: zwave.aeotec_zw130_wallmote_quad
  scene_data: 0
  scene_id: 4
event_type: zwave.scene_activated
platform: event
  condition: []
  action:
  - data:
  entity_id: input_boolean.button_tap
service: input_boolean.turn_on
  - delay: '2'
  - data:
  entity_id: input_boolean.button_tap
service: input_boolean.turn_off

Finally in the automation for each button tap add the test for the tap timer (I’ve shown just button 1 here, repeat for all 4) - again made id unique in your environment:

- id: '1530442018643'
  alias: Wallmote Button 1 tap
  trigger:
  - event_data:
      entity_id: zwave.aeotec_zw130_wallmote_quad
      scene_data: 0
      scene_id: 1
    event_type: zwave.scene_activated
    platform: event
  condition:
  - condition: state
    entity_id: input_boolean.button_tap
    state: 'off'
  action:
  - data:
      entity_id: light.kitchen_cupboards
    service: light.toggle
1 Like

Hi there, you must change parameter 4: Report type to 3 Send Central Scene Command Notification and Configuration Report. After that try to swipe/slide in a button and you will see parameter #9 and #10.

The slide function is supported with multilevel command class and it is not yet supported in OZW, see here.

Hi,

I have also configured my Quad wallmote and is working perfectly except the slide up/down function. As you mention it is not suported by OZW where do you see this ?
I want the wallmote to work with all it’s features. Is it supported by any other Z-wave protocols. Why is Aeotec bringing this to the market with slide functions if you can’t use it.

Regards N.

Hi all,

After a lot of research I have figured out a way to use the slide function on the wallmote. I found a python script (based on https://gist.github.com/clintoncrick/f7aeb59bd314f6cb6b3fd0d103e23ddc) and modified it to detect the slide function.

Configuration
To detect the slide function parameter 4 Report Type of the wallmote must be set to Send Central Scene Command Notification and Configuration report. Once set, two extra parameters will appear: Parameter #9 and Parameter #10 when you swipe up/down on one of the buttons.

Create the following input_number:

  light_step:
    name: 'Step the lights this much'
    initial: 20
    min: 1
    max: 64
    step: 1

#######################################################################
  light_minimum:
    name: 'No dimmer than this'
    initial: 5
    min: 1
    max: 255
    step: 1

#######################################################################
  light_maximum:
    name: 'No brighter than this'
    initial: 255
    min: 50
    max: 255
    step: 1

Python script
Use the following code to extract openzwave logfile and monitor the slide functon, replace OZW_Log file path with your HA installation, the wallmote location and light entities according to your enrivironment:

edited: 10-jan-2019:
I have tidied up the script further and got rid of redundant codes

#!/usr/bin/env python3
Import socket
import requests
from subprocess import Popen, PIPE
import json
##Match Rule
##Match the start of swipe
MATCHER1 = 'Received Configuration report: Parameter=9'
##Match the end of swipe
MATCHER2 = 'Received Configuration report: Parameter=10'
##Match which button is used on the wallmote quad
MATCHER3 = 'Decrypted Packet: 0x00, 0x70, 0x06, 0x09, 0x04'

def extract_value(line):
  value = line.split('=')[-1].strip()
  return int(value)

# variable
event = 'script.dimmer'

##HA information
URI = 'http://192.x.x.x:8123/api/services/script/turn_on'
TOKEN = 'secret'
#TOKEN = False

OZW_LOG = 'YOUR OZW_Log.txt FILE PATH'

debug = True

##Open the tail of our OZW_Log and scan for new lines;
log = Popen(('/usr/bin/tail', '-F', '-n', '0', OZW_LOG), stdout=PIPE)
while True:

##Get most recent line and massage it;
line = log.stdout.readline()
if not line:
  break
line = line.strip().decode('utf-8')


##Fast match
if MATCHER1 not in line:
  if MATCHER2 not in line:
   if MATCHER3 not in line:
    continue

if "Parameter=9" in line:
  nodeID = line.split(',')[1].strip().lower()
  if "node002" in nodeID:
    node = "WALLMOTE LOCATION (eg. bedroom, living room)"
  if "node003" in nodeID:
    node = "OTHER WALLMOTE LOCATION (eg. game room)"

  value9 = extract_value(line)
  continue

elif "Parameter=10" in line:
  value10 = extract_value(line)

elif "Decrypted Packet:" in line:
   button = line.split(',')[-4].replace(' 0x0','').strip()
   continue

if value9 < value10:
  action = 'swipe_up'
else:
  action = 'swipe_down'

if node is not None:
  if "LOCATION WALLMOTE 1" in node:
    if "1" in button:
      light_id = "LIGHT ENTITY_ID"
    if "2" in button:
      light_id = "LIGHT ENTITY_ID"
    if "3" in button:
      light_id = "LIGHT ENTITY_ID"
    if "4" in button:
      light_id = "LIGHT ENTITY_ID"
  elif "LOCATION WALLMOTE 2" in node:
    if "1" in button:             
     light_id = 'LIGHT ENTITY_ID'

if debug:
    print(URI)
if debug:
    print(event)

if event:
    data = {"entity_id": "{0}".format(event), "variables":{"light_id": light_id, "swipe_action": action}}
    if debug:
        print(data)

    if TOKEN:
        resp = requests.post(URI, data=json.dumps(data), headers={'Authorization': 'Bearer {0}'.format(TOKEN), 'content-type': 'application/json'})
    else:
        resp = requests.post(URI, data=json.dumps(data), headers={'content-type': 'application/json'})

    if debug:
        print(resp)

Make sure to generate a Long-Lived Access Tokens in HA and replace ‘secret’ in the script with the generated token.
This script must be running at all times to read the OZW log file (background).

HA script
Use the following code to control the slide up/down functon (dim up/down)

Edited: 10-jan-2019:
I have consolidated 2 scripts (swipe up and swipe down) into one

edited: 12-jan-2019:
Solved a bug that light will be turned off (brightness = 0) when brightness reached its lowest. Now brightness will be set to 5 when its value falls below it.

Dimmer:

  dimmer:
    sequence:
      - service: light.turn_on
        data_template:
          entity_id: '{{ light_id }}'
          brightness: >-
            {% set domain, name = light_id.split('.') %}
            {% set current = states[domain][name].attributes.brightness | int %}
            {% set step = states('input_number.light_step') | int %}
            {% set action = swipe_action %}
            {% if action == 'swipe_up' %}
              {% set next = current + step | int %}
            {% elif action == 'swipe_down' %}
              {% set next = current - step | int %}
            {% endif %}
            {% if next > states('input_number.light_maximum') | int %}
              {% set next = states('input_number.light_maximum') | int %}
            {% elif next < states('input_number.light_minimum') | int %}
              {% set next = states('input_number.light_minimum') | int %}
            {% endif %}

            {{ next }}

This will only work for non z-wave lights. And the dimming is very responsive. I run the scripts on a Pi and it works beautifully. Currently on HA 0.84.6.

The codes I provided here are the courtesy of others in this forum. I would like to thank @petro for his inspiration https://community.home-assistant.io/t/help-with-data-template-using-dynamic-entity-names/50587/20:

or if you want to pull it out of the state machine directly

```
{% set domain, name = entity_id.split('.') %}
{% set current = states[domain][name].attributes.color_temp | int %}

I hope this works for those who want to use the slide function. I am open to any improvement and suggestion to make this ‘workaround’ better and more efficient!

UPDATE 15 Jan 2021 - migrated to openzwave
I just migrated to the new openzwave and now there is no need to run this script in the background. The new solution makes use of the script provided by @phhe here. Thanks to his code there is no need to run the script continuously. The new solution is in this post.

5 Likes

This is awesome, thank you! Any advice on how to run the script continuously on HASS.io?

Unfortunately I don’t know how to run a background task on hass.io. I have a standalone installation on Pi 3B+.
Perhaps you can run it from a headless server and read the OZW_Log file via smb/nfs share? You don’t need to run the script in hass.io as the python script makes use of api calls. It can be run anywhere as long as it has access to OZW_Log file.

Nice work. I had to return my wallmote because it just wouldn’t sense my fingers in general.

Thanks, your code is the final missing link for my solution. I am happy to be able to solve it.

I am quite happy with the wallmote though. Sometimes swipe actions will turn off the light. Just some getting used to I guessed.
So @petro, do you now use a smart wall switch or something similar?

I don’t use anything. Waiting for something that looks sleek, works well, and non-cloud based. Pretty much doesn’t exist. I thought the wallmote would do it, but it just wouldn’t register my fingers. Worked fine for my wife half the time. For me it was 1/10 if that.

Hmm I find the wallmote works almost 99% all the time. I find it the most sleek product on the market atm.

I just tidied up my scripts and got rid of redundant codes.

Can someone advice if I can improve this by using appdaemon? I want to eliminate the background python script altogether. That would be awesome!!

Thanks!

1 Like

Nice work !! thanks for looking into it.

@janus Thanks for your effort in making this work! I’m running into a small (i guess) issue with the python script. I receive the error below, but I’ve no clue what I’m doing wrong?

Traceback (most recent call last):
  File "./swipe.py", line 70, in <module>
    if "1" in button:
NameError: name 'button' is not defined 

This is the python script I use based on your input. The script itself runs fine in the background, but as soon as I swipe a button I receive the error message above and the script crashes:

#!/usr/bin/env python3
import socket
import requests
from subprocess import Popen, PIPE
import json
##Match Rule
##Match the start of swipe
MATCHER1 = 'Received Configuration report: Parameter=9'
##Match the end of swipe
MATCHER2 = 'Received Configuration report: Parameter=10'
##Match which button is used on the wallmote quad
MATCHER3 = 'Decrypted Packet: 0x00, 0x70, 0x06, 0x09, 0x04'

def extract_value(line):
  value = line.split('=')[-1].strip()
  return int(value)

# variable
event = 'script.dimmer'

##HA information
URI = 'https://MYDOMAIN/api/services/script/turn_on'
TOKEN = 'MY SECRET KEY'

OZW_LOG = '/home/homeassistant/.homeassistant/OZW_Log.txt'

debug = True

##Open the tail of our OZW_Log and scan for new lines;
log = Popen(('/usr/bin/tail', '-F', '-n', '0', OZW_LOG), stdout=PIPE)
while True:

  ##Get most recent line and massage it;
  line = log.stdout.readline()
  if not line:
    break
  line = line.strip().decode('utf-8')


  ##Fast match
  if MATCHER1 not in line:
    if MATCHER2 not in line:
     if MATCHER3 not in line:
      continue

  if "Parameter=9" in line:
    nodeID = line.split(',')[1].strip().lower()
    if "node002" in nodeID:
      node = "Livingroom"
    if "node003" in nodeID:
      node = "Kitchen"

    value9 = extract_value(line)
    continue

  elif "Parameter=10" in line:
    value10 = extract_value(line)

  elif "Decrypted Packet:" in line:
     button = line.split(',')[-4].replace(' 0x0','').strip()
     continue

  if value9 < value10:
    action = 'swipe_up'
  else:
    action = 'swipe_down'

  if node is not None:
    if "Livingroom" in node:
      if "1" in button:
        light_id = "light.lamp_boven_bank"
      if "2" in button:
        light_id = "light.lamp_naast_bank"
      if "3" in button:
        light_id = "light.lamp_op_kast"
      if "4" in button:
        light_id = "light.iris_rechts_van_tv"
      elif "Kitchen" in node:
        if "1" in button:
         light_id = 'light.lamp_in_keuken'

  if debug:
      print(URI)
  if debug:
      print(event)

  if event:
      data = {"entity_id": "{0}".format(event), "variables":{"light_id": light_id, "swipe_action": action}}
      if debug:
          print(data)

      if TOKEN:
          resp = requests.post(URI, data=json.dumps(data), headers={'Authorization': 'Bearer {0}'.format(TOKEN), 'content-type': 'application/json'})
      else:
          resp = requests.post(URI, data=json.dumps(data), headers={'content-type': 'application/json'})

      if debug:
          print(resp)

Hi @Janus! Never mind the above question, I’ve managed to fix the error (it had to do with incorrect indenting :expressionless:)

The script runs fine now, although dimming does not work yet :frowning: Do you use this with Hue light bulps or zwave light bulps?

1 Like

Hi there, thanks for trying out my scripts! I used the scripts to manage my Lifx bulbs and strips. Do you have zwave light bulbs? If you do, then you do not need my scripts. Simply associate the group, eg. Dimmer Control via Button 1, with your zwave light bulbs.

I created the scripts because I have no zwave bulbs. As for hue lights, I do not have them so cannot test with them.

If you still have any questions at all, please feel free to let me know!