AlCalzone / node-tradfri-client

Library to talk to IKEA Trådfri Gateways without external binaries
MIT License
264 stars 30 forks source link

Unknown cipher in Electron #594

Closed ItsCoding closed 1 year ago

ItsCoding commented 2 years ago

Hi, saw today that you make an API for Ikeas Smart Home :D but at the moment im not able to authenticate :/ My Gateway runs on FW 1.17.22 Only thing i get is this error message. Am i missing something?

Error: Unknown cipher

 const tradfri = require('node-tradfri-client');
 tradfri.discoverGateway().then((result) => {
    console.log(result);
    const tradfriClient = new tradfri.TradfriClient(result.addresses[0]);
    tradfriClient.authenticate('Quz5XXXXXXXXXfdL').then(
      (identity, psk) => {
        console.log(identity, psk);
      },
      (err) => {
        console.warn(err); //error raised here
       }
     );
 });

Thanks in advance 👍

AlCalzone commented 2 years ago

That's weird, my gateway is on the same firmware, working flawlessly. I thought you might have mistyped the PSK, but if I do that, I get this error instead:

TradfriError: The security code is wrong

You could try restarting the gateway.

ItsCoding commented 2 years ago

Restarted it but still same error :/ do you have any other ideas? Is it maybe a problem that i use your lib in Electron?

VM114 J:\git\traedfri\src\main\preload.js:20 Error: Unknown cipher
    at normalizeReason (VM263 J:\git\traedfri\node_modules\node-coap-client\build\lib\DeferredPromise.js:6)
    at Promise.rej [as reject] (VM263 J:\git\traedfri\node_modules\node-coap-client\build\lib\DeferredPromise.js:14)
    at Socket.onError (VM158 J:\git\traedfri\node_modules\node-coap-client\build\CoapClient.js:1012)
    at Object.onceWrapper (VM14 node:events:514)
    at Socket.emit (VM14 node:events:394)
    at Socket.killConnection (VM181 J:\git\traedfri\node_modules\node-dtls-client\build\dtls.js:227)
    at nextStep (VM181 J:\git\traedfri\node_modules\node-dtls-client\build\dtls.js:109)
    at ClientHandshakeHandler.finishedCallback (VM181 J:\git\traedfri\node_modules\node-dtls-client\build\dtls.js:129)
    at ClientHandshakeHandler.processIncomingMessage (VM258 J:\git\traedfri\node_modules\node-dtls-client\build\DTLS\HandshakeHandler.js:239)
    at Socket.udp_onMessage (VM181 J:\git\traedfri\node_modules\node-dtls-client\build\dtls.js:163)
ItsCoding commented 2 years ago

Okay, tried it in an plain node script and it works! Removed the node_modules folder in my main project and now i get this error with npm install

$ npm i
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.

> postinstall
> ts-node .erb/scripts/check-native-dep.js && electron-builder install-app-deps && cross-env NODE_ENV=development TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.renderer.dev.dll.ts && opencollective-postinstall

  • electron-builder  version=22.13.1
  • loaded configuration  file=package.json ("build" field)
  • installing production dependencies  platform=win32 arch=x64 appDir=J:\git\traedfri\release\app
ERROR in ./node_modules/node-dtls-client/build/lib/AEADCrypto.js 55:46-73
Module not found: Error: Can't resolve 'node-aead-crypto' in 'J:\git\traedfri\node_modules\node-dtls-client\build\lib'
 @ ./node_modules/node-dtls-client/build/TLS/AEADCipher.js 7:21-49
 @ ./node_modules/node-dtls-client/build/TLS/CipherSuite.js 6:19-42
 @ ./node_modules/node-dtls-client/build/DTLS/Handshake.js 5:22-51
 @ ./node_modules/node-dtls-client/build/dtls.js 8:20-47
 @ ./node_modules/node-coap-client/build/CoapClient.js 16:27-54
 @ ./node_modules/node-tradfri-client/build/tradfri-client.js 15:27-54
 @ ./node_modules/node-tradfri-client/build/index.js 45:23-50
 @ dll renderer renderer[7]

webpack compiled with 1 error
npm ERR! code 1
npm ERR! path J:\git\traedfri
npm ERR! command failed
ItsCoding commented 2 years ago

Okay got a litle bit further. I thinks its the same problem as described here #274 . Tested it with the same code and it still outputs this

[
  'md4',        'md5',
  'ripemd160',  'sha1',
  'sha224',     'sha256',
  'sha384',     'sha512',
  'sha512-256'
]

Electron v16.0.5

AlCalzone commented 2 years ago

Oh, electron is definitely the reason.

I'm not sure how and when the dependencies are installed/resolved there. node-tradfri-client indirectly depends on the optional dependency https://github.com/AlCalzone/node-aead-crypto/, which tests during the installation if it is necessary (i.e. if the additional ciphers are supported).

This might be a problem if you're first installing in a Node.js context and then bundling the dependencies for Electron. If you can figure out a better way to make the module optional, I'm all ears.

AlCalzone commented 2 years ago

You can install the module without the preinstall check using

npm install node-aead-crypto --ignore-scripts

but I'm not sure if the module can be resolved then.

ItsCoding commented 2 years ago

Tried many different things today, ended up with a smal nodeJS/express script in the background to avoid the problem :D But thanks for your help ✌

Grüße aus Freiburg

JustJoostNL commented 1 year ago

Hey! I currently have exactly the same issue! @ItsCoding do you have an example solution for me? I can’t get it working.

Thanks in advance!

ItsCoding commented 1 year ago

Hey @koningcool, syr for my late reply 🙈 the thing is, i didnt got it fixed :/ my workarround is just making a small express web server with plain nodejs v16. Thats it and since its working really great. Here is the code for my Express Server

const Tradfri = require("node-tradfri-client");
const express = require("express");
const app = express();
const port = 25587;
const storage = require("node-persist");
const cors = require("cors");

let tradfriClient = null;
let devices = [];
let groups = [];

const getMethods = (obj) =>
  Object.getOwnPropertyNames(obj).filter(
    (item) => typeof obj[item] === "function"
  );

const connectToGateway = async () => {
  await storage.init();
  const result = await Tradfri.discoverGateway();
  const gateway = result.addresses[0];
  tradfriClient = new Tradfri.TradfriClient(result.addresses[0], {
    watchConnection: true,
  });
  let creds = await storage.getItem("credentials");
  if (!creds) {
    const { identity, psk } = await tradfriClient.authenticate(
      "Quz5XDKtCokNQfdL"
    );
    creds = { identity, psk };
    await storage.setItem("credentials", creds);
    console.log("[TRADFRI] Generated PSK and identity");
  }

  try {
    await tradfriClient.connect(creds.identity, creds.psk);
    console.log("[TRADFRI] Connected to gateway");
    tradfriClient
      .on("device updated", (d) => {
        console.log("[TRADFRI] Device updated");
        devices[d.instanceId] = d;
      })
      .observeDevices();
    tradfriClient
      .on("group updated", (g) => {
        console.log("[TRADFRI] Group updated");
        groups[g.instanceId] = g;
      })
      .observeGroupsAndScenes();
  } catch (e) {
    console.error(e);
  }
};

app.use(cors());

app.get("/", (req, res) => {
  console.log("Request for devices received");
  console.log(devices);
  console.log(groups);
  res.json({
    devices: tradfriClient.devices,
    groups: tradfriClient.groups,
  });
});

app.get("/toggleDevice", (req, res) => {
  const deviceId = req.query.deviceId;
  const state = req.query.state;
  //   console.log(devices);
  const device = devices[deviceId].lightList[0];
  // console.log(tradfriClient)

  let parsedState = state == "on" ? true : false;
  console.log("Toggle to " + parsedState);
  device.toggle(parsedState).then((lightResult) => {
    res.json({ status: "ok", info: lightResult });
  });
});

app.get("/setBrightness", (req, res) => {
  const deviceId = req.query.deviceId;
  const state = req.query.state;
  //   console.log(devices);
  const device = devices[deviceId].lightList[0];
  // console.log(tradfriClient)

  console.log("Toggle to " + state);
  device.setBrightness(state).then((lightResult) => {
    res.json({ status: "ok", info: lightResult });
  });
});

app.get("/setHue", (req, res) => {
  const deviceId = req.query.deviceId;
  const state = req.query.state;
  //   console.log(devices);
  const device = devices[deviceId].lightList[0];
  // console.log(tradfriClient)

  console.log("Toggle to " + state);
  device.setColorTemperature(state).then((lightResult) => {
    res.json({ status: "ok", info: lightResult });
  });
});

connectToGateway().then(() => {
  app.listen(port, "localhost", () => {
    console.log(`Example app listening on port ${port}`);
  });
});
JustJoostNL commented 1 year ago

Hey mate! No shame for the late reply! Thanks for answering,

Do you start this script when your Electron app also starts, and how do you start it?

Thanks!

ItsCoding commented 1 year ago

I have it running as background service which I manually install before. But I guess you could spawn a child process through electron and await it until its started :)

JustJoostNL commented 1 year ago

Thanks, I’ll have a look into it later today!

JustJoostNL commented 1 year ago

@ItsCoding I just played around with it a bit, I like it!

Are you okay with me using some/most of the code that you shared in one of my projects?

ItsCoding commented 1 year ago

@koningcool go ahead ;) glhf

AlCalzone commented 1 year ago

I've just release node-aead-crypto@2.2.2 which disables the preinstall check, so you should be able to use the module whether you're developing on an old Node.js version or not. Please give that a try - you might need to edit your lockfile or use npm overrides / yarn resolutions to update to the new version.

AlCalzone commented 1 year ago

If that works, I'll do bumps in the entire dependency chain.

JustJoostNL commented 1 year ago

Thanks! I am going to try this out in electron later today!

JustJoostNL commented 1 year ago

@AlCalzone Hey! I just tried installing node-aead-crypto@2.2.2, but I am getting this strange error, I have never got this one before:

 prebuild-install WARN install No prebuilt binaries found (target=18.7.0 runtime=node arch=x64 libc= platform=win32)

Any solutions? Thanks in advance!

JustJoostNL commented 1 year ago

I think that is because there are no pre-compiled packages uploaded yet by you right? Also when I try to install 2.2.1 (I know that is not working in electron) I get this error:

 node-aead-crypto not needed on this system, since all ciphers are natively supported
AlCalzone commented 1 year ago

prebuild-install WARN install

It's not an error though? AFAIK in this case, the binaries should be compiled on install, instead of being downloaded.

The issue is that since the last release, TravisCI is no longer working and I haven't migrated the prebuild jobs to github actions yet.

JustJoostNL commented 1 year ago

Ahhh, okay! Currently I can’t build it local due some local issues, I will try to fix that, and when are you migrating to GitHub actions?

Also what are your thoughts on this: (I got this on a earlier version)

node-aead-crypto not needed on this system, since all ciphers are natively supported

AlCalzone commented 1 year ago

node-aead-crypto not needed on this system, since all ciphers are natively supported

That was the preinstall check I disabled in 2.2.2. That results in the module not being installed although electron needs it (at least I think that's the underlying problem).

I'll try to fix the prebuild in the coming days. Time's pretty limited right now so I wanted to get the release out there.

JustJoostNL commented 1 year ago

Alright, I fixed some local problems and did try to build it locally, unfortunately not with succes. See below for error.

npm ERR! code 1
npm ERR! path C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto
npm ERR! command failed
npm ERR! command C:\WINDOWS\system32\cmd.exe /d /s /c node lib/install.js
npm ERR! running default installation script
npm ERR! 
npm ERR! > node-aead-crypto@2.2.2 install:default
npm ERR! > prebuild-install || node-gyp rebuild
npm ERR!
npm ERR! Building the projects in this solution one at a time. To enable parallel build, please add the "-m" switch.
npm ERR!   node-aes-ccm.cc
npm ERR! C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\nan\nan.h(2542,6): warning C4996: 'v8::ObjectTemplate::SetAccessor': Do signature check in accessor [C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\build\node-aead-crypto.vcxproj]
npm ERR! C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\src\node-aes-ccm.cc(73,34): error C2660: 'v8::Value::Int32Value': function does not take 0 arguments [C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\build\node-aead-crypto.vcxproj]
npm ERR! C:\Users\[my_username]\AppData\Local\node-gyp\Cache\18.7.0\include\node\v8-value.h(419,40): message : see declaration of 'v8::Value::Int32Value' [C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\build\node-aead-crypto.vcxproj]
npm ERR! C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\src\node-aes-ccm.cc(73,34): message : while trying to match the argument list '()' [C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\build\node-aead-crypto.vcxproj]
npm ERR! C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\src\node-aes-ccm.cc(73,12): error C2737: 'auth_tag_len': const object must be initialized [C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\build\node-aead-crypto.vcxproj]
npm ERR! prebuild-install WARN install No prebuilt binaries found (target=18.7.0 runtime=node arch=x64 libc= platform=win32)
npm ERR! gyp info it worked if it ends with ok
npm ERR! gyp info using node-gyp@9.3.0
npm ERR! gyp info using node@18.7.0 | win32 | x64
npm ERR! gyp info find Python using Python version 3.9.5 found at "C:\Users\[my_username]\AppData\Local\Programs\Python\Python39\python.exe"
npm ERR! gyp info find VS using VS2022 (17.4.33205.214) found at:
npm ERR! gyp info find VS "C:\Program Files\Microsoft Visual Studio\2022\Community"
npm ERR! gyp info find VS run with --verbose for detailed information
npm ERR! gyp info spawn C:\Users\[my_username]\AppData\Local\Programs\Python\Python39\python.exe
npm ERR! gyp info spawn args [
npm ERR! gyp info spawn args   'C:\\Users\\[my_username]\\AppData\\Roaming\\npm\\node_modules\\npm\\node_modules\\node-gyp\\gyp\\gyp_main.py',
npm ERR! gyp info spawn args   'binding.gyp',
npm ERR! gyp info spawn args   '-f',
npm ERR! gyp info spawn args   'msvs',
npm ERR! gyp info spawn args   '-I',
npm ERR! gyp info spawn args   'C:\\Users\\[my_username]\\Documents\\dev\\Projects\\F1MV-Lights-Integration\\node_modules\\node-aead-crypto\\build\\config.gypi',
npm ERR! gyp info spawn args   '-I',
npm ERR! gyp info spawn args   'C:\\Users\\[my_username]\\AppData\\Roaming\\npm\\node_modules\\npm\\node_modules\\node-gyp\\addon.gypi',
npm ERR! gyp info spawn args   '-I',
npm ERR! gyp info spawn args   'C:\\Users\\[my_username]\\AppData\\Local\\node-gyp\\Cache\\18.7.0\\include\\node\\common.gypi',
npm ERR! gyp info spawn args   '-Dlibrary=shared_library',
npm ERR! gyp info spawn args   '-Dvisibility=default',
npm ERR! gyp info spawn args   '-Dnode_root_dir=C:\\Users\\[my_username]\\AppData\\Local\\node-gyp\\Cache\\18.7.0',
npm ERR! gyp info spawn args   '-Dnode_gyp_dir=C:\\Users\\[my_username]\\AppData\\Roaming\\npm\\node_modules\\npm\\node_modules\\node-gyp',
npm ERR! gyp info spawn args   '-Dnode_lib_file=C:\\\\Users\\\\[my_username]\\\\AppData\\\\Local\\\\node-gyp\\\\Cache\\\\18.7.0\\\\<(target_arch)\\\\node.lib',
npm ERR! gyp info spawn args   '-Dmodule_root_dir=C:\\Users\\[my_username]\\Documents\\dev\\Projects\\F1MV-Lights-Integration\\node_modules\\node-aead-crypto',
npm ERR! gyp info spawn args   '-Dnode_engine=v8',
npm ERR! gyp info spawn args   '--depth=.',
npm ERR! gyp info spawn args   '--no-parallel',
npm ERR! gyp info spawn args   '--generator-output',
npm ERR! gyp info spawn args   'C:\\Users\\[my_username]\\Documents\\dev\\Projects\\F1MV-Lights-Integration\\node_modules\\node-aead-crypto\\build',
npm ERR! gyp info spawn args   '-Goutput_dir=.'
npm ERR! gyp info spawn args ]
npm ERR! gyp info spawn C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe
npm ERR! gyp info spawn args [
npm ERR! gyp info spawn args   'build/binding.sln',
npm ERR! gyp info spawn args   '/clp:Verbosity=minimal',
npm ERR! gyp info spawn args   '/nologo',
npm ERR! gyp info spawn args   '/p:Configuration=Release;Platform=x64'
npm ERR! gyp info spawn args ]
npm ERR! gyp ERR! build error
npm ERR! gyp ERR! stack Error: `C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe` failed with exit code: 1
npm ERR! gyp ERR! stack     at ChildProcess.onExit (C:\Users\[my_username]\AppData\Roaming\npm\node_modules\npm\node_modules\node-gyp\lib\build.js:203:23)
npm ERR! gyp ERR! stack     at ChildProcess.emit (node:events:513:28)
npm ERR! gyp ERR! stack     at ChildProcess._handle.onexit (node:internal/child_process:291:12)
npm ERR! gyp ERR! System Windows_NT 10.0.22623
npm ERR! gyp ERR! command "C:\\Program Files\\nodejs\\node.exe" "C:\\Users\\[my_username]\\AppData\\Roaming\\npm\\node_modules\\npm\\node_modules\\node-gyp\\bin\\node-gyp.js" "rebuild"
npm ERR! gyp ERR! cwd C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto
npm ERR! gyp ERR! node -v v18.7.0
npm ERR! gyp ERR! node-gyp -v v9.3.0
npm ERR! gyp ERR! not ok
npm ERR! node:child_process:926
npm ERR!     throw err;
npm ERR!     ^
npm ERR!
npm ERR! Error: Command failed: npm run install:default
npm ERR!     at checkExecSyncError (node:child_process:851:11)
npm ERR!     at execSync (node:child_process:923:15)
npm ERR!     at Object.<anonymous> (C:\Users\[my_username]\Documents\dev\Projects\F1MV-Lights-Integration\node_modules\node-aead-crypto\lib\install.js:22:1)
npm ERR!     at Module._compile (node:internal/modules/cjs/loader:1120:14)
npm ERR!     at Module._extensions..js (node:internal/modules/cjs/loader:1174:10)
npm ERR!     at Module.load (node:internal/modules/cjs/loader:998:32)
npm ERR!     at Module._load (node:internal/modules/cjs/loader:839:12)
npm ERR!     at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
npm ERR!     at node:internal/main/run_main_module:17:47 {
npm ERR!   status: 1,
npm ERR!   signal: null,
npm ERR!   output: [ null, null, null ],
npm ERR!   pid: 28204,
npm ERR!   stdout: null,
npm ERR!   stderr: null
npm ERR! }
npm ERR!
npm ERR! Node.js v18.7.0

Since there is probably not an easy solution to this, I think I'll just wait until the GitHub Actions are setup, so I can use the prebuilt.

AlCalzone commented 1 year ago

Damn... I had the same issue and could only fix it by setting up a devcontainer with Node.js 8 🙈

I'm afraid the entire thing needs an overhaul, including migrating to N-API.

JustJoostNL commented 1 year ago

I'm afraid the entire thing needs an overhaul, including migrating to N-API.

What do you mean exactly with this? And what do you recommend to me doing now? I am not super familiar with devcontainers.

AlCalzone commented 1 year ago

Not much you can do I'm afraid. I would have to rework how this module is built to make it compile on newer Node.js versions.

JustJoostNL commented 1 year ago

Alright, in that case, keep me up to date!

JustJoostNL commented 1 year ago

Btw, maybe consider re-opening this, since this is still an issue?

JustJoostNL commented 1 year ago

Not much you can do I'm afraid. I would have to rework how this module is built to make it compile on newer Node.js versions.

@AlCalzone You have any updates on this?

AlCalzone commented 1 year ago

I'm actually working on this now. It's a bit challenging to get to work though: https://github.com/AlCalzone/node-aead-crypto/pull/79

AlCalzone commented 1 year ago

@JustJoostNL can you try using node-aead-crypto@3.0.0-alpha.0 like described in https://github.com/AlCalzone/node-tradfri-client/issues/594#issuecomment-1353776666?

JustJoostNL commented 1 year ago

Thanks for creating some time for this issue! I appreciate that. I will try the new version in Electron later today!

JustJoostNL commented 1 year ago

@AlCalzone Hey! I just tried using node-aead-crypto@3.0.0-alpha.0. Unfortunately, I still get an Unknown cipher error.

I have added this to my package.json:

"overrides": {
    "node-aead-crypto": "3.0.0-alpha.0"
  },

So it overwrites the dependency.

Any idea what goes wrong here?

Thanks for you time!

AlCalzone commented 1 year ago

is your project public so I could have a look?

JustJoostNL commented 1 year ago

My project is open-source, you can find it here.

The function that I run is in the main.js at line 1013

AlCalzone commented 1 year ago

Ok, I got a bit further... This check https://github.com/AlCalzone/node-dtls-client/commit/cf2492be298eccfed3492745165fe16b57cf9894#diff-b39ae3048fb6d928ca97968d5abadbee403a724fded657537d1afd276f0a2fb0 needed to be changed because it essentially ignored the Electron runtime and always used the native crypto module.

After changing that, I got your project to actually use node-aead-crypto, but then ran into this issue https://github.com/nodejs/abi-stable-node/issues/441 which I solved by updating electron. Then I got this error, which is actually success:

Error: The security code is wrong
    at TradfriClient.<anonymous> (/home/dominic/Repositories/F1MV-Lights-Integration/node_modules/node-tradfri-client/build/tradfri-client.js:189:43)
AlCalzone commented 1 year ago

So, in short:

npm update electron
npm update node-dtls-client

(the latter should not be necessary on a clean install, this just updates your package-lock and what is actually installed).

If you can confirm this works for you too, I'll release v3 of the aead library.

JustJoostNL commented 1 year ago

Can confirm this works! Thanks so much for helping!

AlCalzone commented 1 year ago

node-tradfri-client v3.2.0 will be out in a couple of minutes and fixes this.