WebThingsIO / zwave-adapter

Z-Wave adapter add-on for WebThings Gateway
Mozilla Public License 2.0
15 stars 20 forks source link

Issues adding First Alert ZCOMBO-G smoke alarm #106

Closed NuskyZ closed 4 years ago

NuskyZ commented 4 years ago

Hello,

I recently started using Mozilla Webthings and I've really enjoyed how easy it's been to set everything up. The only snag I've hit so far is a smoke alarm that I recently purchased.

The product is a First Alert ZCOMBO-G smoke detector - https://products.z-wavealliance.org/products/3709

When adding the unit to WebThings, the add device function times out at first, but then displays a generic thing icon with a battery indicator and wake-up interval. I assume that, because it's a fairly new device, it isn't recognized fully by the WebThings library.

I was wondering if there might be some way I could either add it myself, or maybe learn if there are plans to add it down the track. The main forum suggested I take a look at zwave-classifier.js and post an issue here to get me on the right track.

Appreciating any help.

mrstegeman commented 4 years ago

That was me. 😄

Here are some good documents:

Most of the code will go in zwave-classifier.js and in zwave-property.js.

NuskyZ commented 4 years ago

This is awesome, thanks so much! I'll take a look over it all and see what I can do.

NuskyZ commented 4 years ago

I've been looking into this during some of my spare time this week, but I'm having a few issues. I cloned the repositories and installed YAML. Then:

1) I modified the backup script a little to point to the correct directory, but there seems to be a file missing when npm runs and I'm not sure if it's starting up properly. I get some errors:

pm ERR! path /home/pi/package.json npm ERR! code ENOENT npm ERR! errno -2 npm ERR! syscall open npm ERR! enoent ENOENT: no such file or directory, open '/home/pi/package.json' npm ERR! enoent This is related to npm not being able to find a file. npm ERR! enoent

npm ERR! A complete log of this run can be found in: npm ERR! /home/pi/.npm/_logs/2020-01-17T16_53_47_738Z-debug.log

Then, 2) I just can't seem to get the CLI program to connect to my gateway. This is about as far as I get:

~/cli $ ./c.py gateway https://localhost:8080 /home/pi/cli/cli/log_setup.py:18: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details. config = yaml.load(cfg_file.read()) cli https://localhost:8080> devices Unable to connect to server: https://localhost:8080/debug/devices Traceback (most recent call last): File "./c.py", line 3, in from cli import main File "/home/pi/cli/cli/main.py", line 86, in main() File "/home/pi/cli/cli/main.py", line 73, in main cmd_line.auto_cmdloop(' '.join(args.cmd)) File "/home/pi/cli/cli/command_line.py", line 291, in auto_cmdloop stop = self.auto_cmdloop_internal(line) File "/home/pi/cli/cli/command_line.py", line 301, in auto_cmdloop_internal self.onecmd(line) File "/home/pi/cli/cli/command_line.py", line 345, in onecmd return Cmd.onecmd(self, line) File "/usr/lib/python3.7/cmd.py", line 217, in onecmd return func(arg) File "/home/pi/cli/cli/command_line.py", line 439, in do_gateway return GatewayCommandLine(gateway).auto_cmdloop('') File "/home/pi/cli/cli/command_line.py", line 291, in auto_cmdloop stop = self.auto_cmdloop_internal(line) File "/home/pi/cli/cli/command_line.py", line 299, in auto_cmdloop_internal self.cmdloop() File "/home/pi/cli/cli/command_line.py", line 352, in cmdloop return Cmd.cmdloop(self, *args, **kwargs) File "/usr/lib/python3.7/cmd.py", line 138, in cmdloop stop = self.onecmd(line) File "/home/pi/cli/cli/command_line.py", line 345, in onecmd return Cmd.onecmd(self, line) File "/usr/lib/python3.7/cmd.py", line 217, in onecmd return func(arg) File "/home/pi/cli/cli/command_line.py", line 501, in do_devices if len(devices) > 0: TypeError: object of type 'NoneType' has no len()

I'm not sure what else I can do from here.

mrstegeman commented 4 years ago

~/cli $ ./c.py gateway https://localhost:8080

That should be http://, not https://.

mrstegeman commented 4 years ago

As for the backup script, you should put it inside the gateway directory (~/mozilla-iot/gateway) and run it from there.

NuskyZ commented 4 years ago

Thanks for getting back so quickly. I moved the backup script, but now it appears a different file "webpack" is missing. Is there some development repository I'm supposed to download here that I'm missing?

Backing up /home/pi/.mozilla-iot/addons to /home/pi/addon-backup/2020-01-17-124235 ...

webthings-gateway@0.10.0 start /home/pi/mozilla-iot/gateway webpack --display errors-only && node build/gateway.js "-d"

sh: 1: webpack: not found npm ERR! file sh npm ERR! code ELIFECYCLE npm ERR! errno ENOENT npm ERR! syscall spawn npm ERR! webthings-gateway@0.10.0 start: webpack --display errors-only && node build/gateway.js "-d" npm ERR! spawn ENOENT npm ERR! npm ERR! Failed at the webthings-gateway@0.10.0 start script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in: npm ERR! /home/pi/.npm/_logs/2020-01-17T18_42_43_929Z-debug.log

I also tried the CLI command using http, but it still reports that it's unable to connect. Presumably because of the above error.

Thanks in advance.

mrstegeman commented 4 years ago

Run npm install inside the gateway directory.

NuskyZ commented 4 years ago

That's fixed the webpack issue, but now npm is complaining about an address conflict on startup.

2020-01-17 13:35:20.018 INFO : Service Discovery: state changed to: true 2020-01-17 13:35:20.608 ERROR : Error: listen EADDRINUSE :::4443 at Server.setupListenHandle [as _listen2] (net.js:1360:14) at listenInCluster (net.js:1401:12) at Server.listen (net.js:1485:7) at promises.push.Promise (/home/pi/mozilla-iot/gateway/build/webpack:/src/app.js:133:1) at new Promise () at startHttpsGateway (/home/pi/mozilla-iot/gateway/build/webpack:/src/app.js:132:1) at serverStartup.promise.TunnelService.userSkipped.then (/home/pi/mozilla-iot/gateway/build/webpack:/src/app.js:381:1) at npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! webthings-gateway@0.10.0 start: webpack --display errors-only && node build/gateway.js "-d" npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the webthings-gateway@0.10.0 start script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

Webthings appears active when I access it via browser on the local network. But running the CLI gives me the same connection error as before.

I thought it might be trying to start up npm while another instances of the gateway was active. I tried killing all processes and running the script again, but it still complains about that port being busy and the script won't finish.

mrstegeman commented 4 years ago

While you're doing testing and restarting via the script, you should do the following:

sudo systemctl stop mozilla-iot-gateway
sudo systemctl disable mozilla-iot-gateway  # optional

After you're all done, you can re-enable the system service as follows:

sudo systemctl start mozilla-iot-gateway
sudo systemctl enable mozilla-iot-gateway
NuskyZ commented 4 years ago

Thanks! It seems to be working and now npm is running and I can see the log being output to the terminal. It's reporting the status changes for all the zwave devices as they trigger.

However, the CLI still isn't connecting. I've tried substituting 'localhost' with the gateway name and 127.0.0.1 but that doesn't seem to help.

Does WebThings have a built in firewall or some other background protection working here that I need to disable first? Or maybe there's a login function I need to go through before I can use the 'devices' command?

mrstegeman commented 4 years ago

If you have the tunneling service set up, you'll probably need to change the URL to https://localhost:4443.

NuskyZ commented 4 years ago

Mrstegeman, you're a gentleman and a scholar!

The CLI connected and I've been able to extract device information using the 'info' command. I'll play around with this over the weekend and see what I can come up with.

Again, thanks so much.

mrstegeman commented 4 years ago

Great! Hope you can get your device working properly.

NuskyZ commented 4 years ago

Okay, it's clear getting this device recognized properly will require more than the coding skills of a mere Padawan such as myself.

I'm looking at this segment in zwave-classifier.js that would be useful:

const NOTIFICATION_SENSOR = {
  [NOTIFICATION_SMOKE_DETECTOR]: {// 1
    name: 'smoke',
    '@type': ['Alarm'],
    propertyName: 'on',
    propertyDescr: {
      '@type': 'AlarmProperty',
      type: 'boolean',
      label: 'Smoke',
      description: 'Smoke Detector',
      readOnly: true,
    },
    valueListMap: [false, true],
  },

But the problem is the ZCOMBO-G doesn't appear to send a boolean code for the ALARM (113) state. Rather, it sends byte values depending on the type of alarm that is triggered (presumedly test, smoke & CO) and the alarm level:

  "48-113-1-512": {
      "value_id": "48-113-1-512",
      "node_id": 48,
      "class_id": 113,
      "type": "byte",
      "genre": "user",
      "instance": 1,
      "index": 512,
      "label": "Alarm Type",
      "units": "",
      "help": "Alarm Type Received",
      "read_only": true,
      "write_only": false,
      "min": 0,
      "max": 255,
      "is_polled": false,
      "value": 13
    },
    "48-113-1-513": {
      "value_id": "48-113-1-513",
      "node_id": 48,
      "class_id": 113,
      "type": "byte",
      "genre": "user",
      "instance": 1,
      "index": 513,
      "label": "Alarm Level",
      "units": "",
      "help": "Alarm Level Received",
      "read_only": true,
      "write_only": false,
      "min": 0,
      "max": 255,
      "is_polled": false,
      "value": 255
    }

This is going to require extra coding to interpret the values and map the proper UI icons for SAFE, SMOKE, CO, TEST, etc. I never even looked at JavaScript before this, so it'd take me some time to get up to speed with how the whole project fits together.

What's best for me to do in this case? Should I upload the info file I extracted from the device using the CLI, and maybe others in the project might take up the challenge?

Appreciating your help.

mrstegeman commented 4 years ago

Should I upload the info file I extracted from the device using the CLI

Yes, please do.

NuskyZ commented 4 years ago

Here's what I extracted.

FirstAlert-ZCOMBOG-Smoke-CO-Detector.json.gz

mrstegeman commented 4 years ago

Ok, I've opened #107, which should add support for your device. The only thing I'm missing is the proper values for the "Alarm Type" property. Would it be possible for you to do some testing to find those? You'd have to run through the following scenarios, dumping the JSON for each:

  1. Clear (no alarms)
  2. Smoke
  3. Carbon monoxide
  4. Test
NuskyZ commented 4 years ago

Wow! Thanks for getting onto that so quickly. I can do the tests and get the codes over the next day or so.

I also see there's an XML file for the device on the zwave alliance page. It seems to describe some notification states for the smoke and CO sensors, along with other states like maintenance, etc. Eg:

<NotificationType>
  <Id>0</Id>
  <notification_type>Smoke Alarm</notification_type>
  <notification_type_key>0x01</notification_type_key>
  <notification>Sensor status: Smoke detected</notification>
  <notification_key>0x02</notification_key>
</NotificationType>

Would that be of any use? The link to the file is: https://products.z-wavealliance.org/Products/3709/XML

(For some reason, Github won't let me upload it to the forum.)

mrstegeman commented 4 years ago

I'm new to Z-Wave, so I'm trying to make sense of all the specs and how they map to individual properties. I think physical values from your device should make things more clear to me.

For (my own) reference, SDS13781, sections 4.3 and 4.74.

NuskyZ commented 4 years ago

Hey there again. I had some free time, so I did some testing with the unit while watching the logfiles to see what values get sent. Here's what I found:

PULSE (seems to send this hourly)

zwave: node50 valueChanged: 50-113-1-512:Alarm Type = 13 (no property found) zwave: node50 valueChanged: 50-113-1-513:Alarm Level = 255 (no property found)

TEST BUTTON PRESSED

ON zwave: node50 valueChanged: 50-113-1-512:Alarm Type = 12 (no property found) zwave: node50 valueChanged: 50-113-1-513:Alarm Level = 255 (no property found) OFF zwave: node50 valueChanged: 50-113-1-512:Alarm Type = 12 (no property found) zwave: node50 valueChanged: 50-113-1-513:Alarm Level = 0 (no property found) zwave: node50 valueChanged: 50-128-1-0:Battery Level property: batteryLevel = 99 %

SMOKE DETECTED

ON zwave: node50 valueChanged: 50-113-1-512:Alarm Type = 1 (no property found) zwave: node50 valueChanged: 50-113-1-513:Alarm Level = 255 (no property found) CLEAR zwave: node50 valueChanged: 50-113-1-512:Alarm Type = 1 (no property found) zwave: node50 valueChanged: 50-113-1-513:Alarm Level = 0 (no property found)

I'm not sure how to safely do a CO2 test, though. Perhaps it'd read something like "Alarm Type = 2" with Alarm Level 255 for ON and 0 for OFF.

Hope this helps.

mrstegeman commented 4 years ago

Thank you! That's making a lot more sense now.

Can you take a look at this patch and see if it the logic at least looks sane to you? If so, I'll merge and build a release so that you can actually test it out.

One thing I was undecided about was whether or not I should set both alarm properties to active when the test button is pushed.

NuskyZ commented 4 years ago

From what I understand from it, I think that's going to work. It triggers on either 1 or 2, but doesn't false trigger on the pulse. As for the test case, I don't know if there's a "TEST" icon that could just be displayed bit. if not, but maybe activating both properties would be best.

Thanks, as always, for your help.

mrstegeman commented 4 years ago

Ok, I made the test function trigger both alarms.

I've just release v0.10.4 of the add-on, so let me know if you have any further issues!

NuskyZ commented 4 years ago

Wonderful. Triggering a test sets off the alarm with both smoke and CO2 nodes activating. The battery node reports properly too. Now I should really try to learn some JavaScript...

Thanks so much yet again. This'll be great to keep an eye on the house while on holidays.