zehnm/neeo-mystrom-switch

Auto discovery of myStrom WiFi Switch v1 devices

Opened this issue · 1 comments

zehnm commented

The auto discovery of WiFi Switch v2 devices is already implemented and working fine. Version 2 is the currently available device with integrated temperature sensor. V1 devices have the same REST API but don't have a temperature sensor and don't announce themself by UDP broadcast on port 7979.

Enhancement: auto discovery for v1 switches.

Official information received from mystrom.ch support:

in case of WSW - WiFi Switch v1 it broadcast itself over UPNP.

Unfortunately I've been unable to discover a v1 switch with UPNP. I've tried various tools, libraries and my own code under Linux and OSX.
My analysis so far:

  • Port scan on v1 switch revealed standard UPNP port 1900:
PORT     STATE         SERVICE
1900/udp open|filtered upnp
  • myStrom v1 switch doesn’t respond to UPNP ssdp:discover requests to standard multicast address and port 239.255.255.250:1900. Tried with search target (ST) ssdp:all and upnp:rootdevice:
#!/usr/bin/env python
import socket

msg = \
    'M-SEARCH * HTTP/1.1\r\n' \
    'HOST:239.255.255.250:1900\r\n' \
    'MAN:"ssdp:discover"\r\n' \
    'MX:5\r\n' \
    'ST:ssdp:all\r\n' \
    '\r\n'

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.settimeout(10)
s.sendto(msg, ('239.255.255.250', 1900) )

try:
    while True:
        data, addr = s.recvfrom(8192)
        print addr, data
except socket.timeout:
    pass
  • myStrom v1 switch doesn’t advertise itself (multicasting advertisement messages to 239.255.255.250:1900) with ssdp:alive:
#!/usr/bin/env python
import socket
import struct

MCAST_GRP = '239.255.255.250'
MCAST_PORT = 1900

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((MCAST_GRP, MCAST_PORT))  # use '' instead of MCAST_GRP to listen to all groups on MCAST_PORT
mreq = struct.pack("4sl", socket.inet_aton(MCAST_GRP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
    data, addr = sock.recvfrom(8192)
    print addr, data
  • No UPNP traffic detected with Wireshark, only MDNS Queries once in a while.

I’m able to discover all other UPNP devices on my network (router, Logitech Harmony, TV, Radio, NEEO remote, Plex), with upnp tools, Wireshark and my own code. Therefore I assume something is wrong or ‘special’ with the myStrom WiFi Switch v1.

Does anyone have an idea or further information?

zehnm commented

MDNS analysis:

  • not active by default
  • device starts sending MDNS queries only after one clicks through the myStrom app, device, settings, Apple HomeKit
  • MDNS is of type hap (Apple Homekit afaik)

Node.js test:

'use strict';
const bonjour = require('bonjour')();

function printObject(o) {
  let out = '';
  Object.getOwnPropertyNames(o).forEach( (name, index) => {
    out += (index > 0 ? ',' : '') + name + '=' + o[name];
  });
  return out;
}

function serviceUpListener(service) {
  if (!service || !service.txt || !service.host) {
    return;
  }
  if (service.host.startsWith('myStrom-Switch')) {
    console.log('MDNS discovered "%s": host=%s, MAC=%s, txt=[%s]', service.name, service.host, service.txt.id, printObject(service.txt));
  }
}

const mdnsBrowser = bonjour.find({ type: 'hap' }, serviceUpListener);
mdnsBrowser.start();

Output (with masked mac addresses):

MDNS discovered "Switch-ef0011": host=myStrom-Switch-ef0011.local, MAC=de:ad:be:ef:00:11, txt=[c#=1,ff=0,id=de:ad:be:ef:00:11,md=Switch-ef0011,pv=1.0,s#=2,sf=1,ci=8]
MDNS discovered "Outlet ef0022": host=myStrom-Switch-ef0022.local, MAC=de:ad:be:ef:00:22, txt=[c#=1025720861,ff=0,id=de:ad:be:ef:00:22,md=Outlet ef0022,pv=1.0,s#=1,sf=1,ci=7]
  • "Switch-ef0011" is a v1 switch
  • "Outlet ef0022" is a v2 switch