forty2 / haiku-senseme

Control SenseME enabled devices from Haiku with Node.js
MIT License
1 stars 7 forks source link

getting properties from L series fans #2

Open jgc94131 opened 7 years ago

jgc94131 commented 7 years ago

I have three L series fans which I updated recently via the iOS app. I'm unable to read some basic properties from them.

bigAssApi = require("haiku-senseme");

bigAssApi.SenseME
  .on('founddevice', dev => {
    console.log(`Found:\n name ${dev.name}\n id ${dev.id}\n type ${dev.type}\n i
p ${dev.ip}`);
    console.log(`  fan power: ${dev.fan.power.value}`);
    console.log(`  fan speed: ${dev.fan.speed.value}`);
    console.log(`  light power: ${dev.light.power.value}`);
    console.log(`  light brightness: ${dev.light.brightness.value}`);
  })
  .on('lostdevice', dev => {
    console.log(`Lost: ${dev.name}`);
  })
  .discover();

Produces

$ node example.js
server listening 0.0.0.0:31415
Found:
 name Fan
 id 20:F8:5E:D3:54:88
 type FAN,LSERIES
 ip 192.168.7.78
  fan power: undefined
  fan speed: NaN
  light power: undefined
  light brightness: NaN
Found:
 name Fan
 id 20:F8:5E:E8:85:9F
 type FAN,LSERIES
 ip 192.168.7.105
  fan power: undefined
  fan speed: NaN
  light power: undefined
  light brightness: NaN
 name Fan
 id 20:F8:5E:F2:4C:E6
 type FAN,LSERIES
 ip 192.168.7.116
  fan power: undefined
  fan speed: NaN
  light power: undefined
  light brightness: NaN

I'm not sure if I'm using the module correctly, or if the update has broken this module, or something else.

$ node --version
v6.10.3
$ npm install haiku-senseme --save
npm WARN saveError ENOENT: no such file or directory, open '/home/pi/haiku-sense-me/package.json'
/home/pi/haiku-sense-me
└── haiku-senseme@1.1.0

npm WARN enoent ENOENT: no such file or directory, open '/home/pi/haiku-sense-me/package.json'
npm WARN haiku-sense-me No description
npm WARN haiku-sense-me No repository field.
npm WARN haiku-sense-me No README data
npm WARN haiku-sense-me No license field.
forty2 commented 7 years ago

Well, there's good news and less-good news: the good news is, the fundamental protocol hasn't changed. The less good news is, with the new update, it looks like the timing of responses from devices has changed enough that at the time the founddevice event is emitted we still haven't received the initial data from the devices yet.

One quick and dirty way to work around this is a simple setTimeout to delay the request a little bit:

bigAssApi = require("haiku-senseme");

bigAssApi.SenseME
  .on('founddevice', dev => {
    console.log(`Found:\n name ${dev.name}\n id ${dev.id}\n type ${dev.type}\n ip ${dev.ip}`);
    setTimeout(() => {
        console.log(`  fan power: ${dev.fan.power.value}`);
        console.log(`  fan speed: ${dev.fan.speed.value}`);
        console.log(`  light power: ${dev.light.power.value}`);
        console.log(`  light brightness: ${dev.light.brightness.value}`);
    }, 250);
  })
  .on('lostdevice', dev => {
    console.log(`Lost: ${dev.name}`);
  })
  .discover();

A slightly more sophisticated method would be to listen for change events and wait for them to settle down before proceeding:

bigAssApi = require("haiku-senseme");

bigAssApi.SenseME
    .on('founddevice', dev => {
        console.log(`Found:\n name ${dev.name}\n id ${dev.id}\n type ${dev.type}\n ip ${dev.ip}`);

        afterSettled
            .call(
                dev
                    .listenAll(),
                'change',
                100,
                () => {
                    console.log(`  fan power: ${dev.fan.power.value}`);
                    console.log(`  fan speed: ${dev.fan.speed.value}`);
                    console.log(`  light power: ${dev.light.power.value}`);
                    console.log(`  light brightness: ${dev.light.brightness.value}`);
                }
            );
    })
    .on('lostdevice', dev => {
        console.log(`Lost: ${dev.name}`);
    })
    .discover();

function afterSettled(event, settleTime, callback) {
    this.addListener(event, handleEvent);

    let timeout;
    function handleEvent() {
        if (timeout) {
            clearTimeout(timeout);
        }
        timeout = setTimeout(() => {
            callback();
            this.removeListener(event, handleEvent);
            timeout = null;
        }, settleTime);
    }
}

Hopefully one of these two solutions will work for you on a temporary basis. I intend to find a way to fix this in the library itself, but I probably won't have time to get to it until this weekend.