@camstack/addon-provider-homematic 1.2.171 → 1.2.172

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.2.172] - 2026-10-31
11
+
12
+ ### Changed
13
+
14
+ - The CCU network scan now finds a CCU that answers the probe with a JSON-RPC error, a WebUI username alone (empty password) now unlocks device names, and a missing-names warning is logged.
15
+
10
16
  ## [1.2.171] - 2026-10-31
11
17
 
12
18
  ### Changed
package/dist/addon.js CHANGED
@@ -117895,11 +117895,12 @@ function enabledInterfaces(config) {
117895
117895
  /**
117896
117896
  * Build the `HomematicOptions` the wrapped library constructor expects
117897
117897
  * from the validated addon config. Pure: same config in → same options
117898
- * out. Credentials are only forwarded when both fields are non-empty so
117899
- * the library skips the JSON-RPC hub layer cleanly when they're absent.
117898
+ * out. Credentials are forwarded when a username is set (the password may be
117899
+ * empty on a CCU without WebUI authentication); without one the library skips
117900
+ * the JSON-RPC hub layer cleanly.
117900
117901
  */
117901
117902
  function toHomematicOptions(config) {
117902
- const hasCredentials = config.username.length > 0 && config.password.length > 0;
117903
+ const hasCredentials = config.username.length > 0;
117903
117904
  const callbackHost = config.callbackHost.length > 0 ? config.callbackHost : inferCallbackHost(config.host) ?? "";
117904
117905
  const interfaces = enabledInterfaces(config);
117905
117906
  return {
@@ -120780,6 +120781,10 @@ var HOMEMATIC_DISCOVERY_MODES = [{
120780
120781
  tls: false,
120781
120782
  acceptStatus: [200]
120782
120783
  }];
120784
+ /** A JSON-RPC reply: it echoes `version` or `id`, and carries a `result` and an `error` member. */
120785
+ function isJsonRpcEnvelope(parsed) {
120786
+ return (Reflect.has(parsed, "version") || Reflect.has(parsed, "id")) && Reflect.has(parsed, "result") && Reflect.has(parsed, "error");
120787
+ }
120783
120788
  /**
120784
120789
  * Read the answer of `CCU.getAuthEnabled`, the question the WebUI asks before
120785
120790
  * it shows a login. A CCU answers a boolean; one that already requires a login
@@ -120799,7 +120804,7 @@ function parseAuthEnabledAnswer(status, text) {
120799
120804
  if (typeof error !== "object") return null;
120800
120805
  const message = Reflect.get(error, "message");
120801
120806
  const code = Reflect.get(error, "code");
120802
- return typeof message === "string" && message.toLowerCase().startsWith("access denied") || code === 401 || code === -32001 ? { authEnabled: true } : null;
120807
+ return typeof message === "string" && message.toLowerCase().startsWith("access denied") || code === 401 || code === -32001 || isJsonRpcEnvelope(parsed) ? { authEnabled: true } : null;
120803
120808
  }
120804
120809
  const result = Reflect.get(parsed, "result");
120805
120810
  if (result === true || result === "true") return { authEnabled: true };
@@ -120910,6 +120915,7 @@ var HmIntegrationManager = class {
120910
120915
  #facade = null;
120911
120916
  #status = "disconnected";
120912
120917
  #deviceCount = 0;
120918
+ #namesAvailable = true;
120913
120919
  #lastCheckedAt = null;
120914
120920
  #error = null;
120915
120921
  /** Active event-listener disposers, cleared on stop. */
@@ -120960,7 +120966,8 @@ var HmIntegrationManager = class {
120960
120966
  info: {
120961
120967
  host: this.#connection.host,
120962
120968
  tls: this.#connection.tls,
120963
- deviceCount: this.#deviceCount
120969
+ deviceCount: this.#deviceCount,
120970
+ namesAvailable: this.#namesAvailable
120964
120971
  },
120965
120972
  lastCheckedAt: this.#lastCheckedAt,
120966
120973
  error: this.#error
@@ -120983,7 +120990,20 @@ var HmIntegrationManager = class {
120983
120990
  this.#facade = facade;
120984
120991
  this.#attachListeners(facade);
120985
120992
  await facade.start();
120986
- this.#deviceCount = facade.devices().length;
120993
+ const devices = facade.devices();
120994
+ this.#deviceCount = devices.length;
120995
+ this.#namesAvailable = devices.length === 0 || devices.some((d) => (d.name ?? "").length > 0);
120996
+ if (!this.#namesAvailable) {
120997
+ const credentialsSet = this.#connection.username.length > 0;
120998
+ this.#logger.warn("HmIntegrationManager: device names unavailable — devices are listed by address", {
120999
+ tags: { integrationId: this.#id },
121000
+ meta: {
121001
+ devices: devices.length,
121002
+ credentialsSet,
121003
+ hint: credentialsSet ? "WebUI login set but the CCU returned no names; check the username (an empty password is valid on a CCU without WebUI authentication)" : "set a WebUI username (and password if the CCU has one) on the integration"
121004
+ }
121005
+ });
121006
+ }
120987
121007
  this.#lastCheckedAt = Date.now();
120988
121008
  this.#status = "connected";
120989
121009
  this.#error = null;
package/dist/addon.mjs CHANGED
@@ -117896,11 +117896,12 @@ function enabledInterfaces(config) {
117896
117896
  /**
117897
117897
  * Build the `HomematicOptions` the wrapped library constructor expects
117898
117898
  * from the validated addon config. Pure: same config in → same options
117899
- * out. Credentials are only forwarded when both fields are non-empty so
117900
- * the library skips the JSON-RPC hub layer cleanly when they're absent.
117899
+ * out. Credentials are forwarded when a username is set (the password may be
117900
+ * empty on a CCU without WebUI authentication); without one the library skips
117901
+ * the JSON-RPC hub layer cleanly.
117901
117902
  */
117902
117903
  function toHomematicOptions(config) {
117903
- const hasCredentials = config.username.length > 0 && config.password.length > 0;
117904
+ const hasCredentials = config.username.length > 0;
117904
117905
  const callbackHost = config.callbackHost.length > 0 ? config.callbackHost : inferCallbackHost(config.host) ?? "";
117905
117906
  const interfaces = enabledInterfaces(config);
117906
117907
  return {
@@ -120781,6 +120782,10 @@ var HOMEMATIC_DISCOVERY_MODES = [{
120781
120782
  tls: false,
120782
120783
  acceptStatus: [200]
120783
120784
  }];
120785
+ /** A JSON-RPC reply: it echoes `version` or `id`, and carries a `result` and an `error` member. */
120786
+ function isJsonRpcEnvelope(parsed) {
120787
+ return (Reflect.has(parsed, "version") || Reflect.has(parsed, "id")) && Reflect.has(parsed, "result") && Reflect.has(parsed, "error");
120788
+ }
120784
120789
  /**
120785
120790
  * Read the answer of `CCU.getAuthEnabled`, the question the WebUI asks before
120786
120791
  * it shows a login. A CCU answers a boolean; one that already requires a login
@@ -120800,7 +120805,7 @@ function parseAuthEnabledAnswer(status, text) {
120800
120805
  if (typeof error !== "object") return null;
120801
120806
  const message = Reflect.get(error, "message");
120802
120807
  const code = Reflect.get(error, "code");
120803
- return typeof message === "string" && message.toLowerCase().startsWith("access denied") || code === 401 || code === -32001 ? { authEnabled: true } : null;
120808
+ return typeof message === "string" && message.toLowerCase().startsWith("access denied") || code === 401 || code === -32001 || isJsonRpcEnvelope(parsed) ? { authEnabled: true } : null;
120804
120809
  }
120805
120810
  const result = Reflect.get(parsed, "result");
120806
120811
  if (result === true || result === "true") return { authEnabled: true };
@@ -120911,6 +120916,7 @@ var HmIntegrationManager = class {
120911
120916
  #facade = null;
120912
120917
  #status = "disconnected";
120913
120918
  #deviceCount = 0;
120919
+ #namesAvailable = true;
120914
120920
  #lastCheckedAt = null;
120915
120921
  #error = null;
120916
120922
  /** Active event-listener disposers, cleared on stop. */
@@ -120961,7 +120967,8 @@ var HmIntegrationManager = class {
120961
120967
  info: {
120962
120968
  host: this.#connection.host,
120963
120969
  tls: this.#connection.tls,
120964
- deviceCount: this.#deviceCount
120970
+ deviceCount: this.#deviceCount,
120971
+ namesAvailable: this.#namesAvailable
120965
120972
  },
120966
120973
  lastCheckedAt: this.#lastCheckedAt,
120967
120974
  error: this.#error
@@ -120984,7 +120991,20 @@ var HmIntegrationManager = class {
120984
120991
  this.#facade = facade;
120985
120992
  this.#attachListeners(facade);
120986
120993
  await facade.start();
120987
- this.#deviceCount = facade.devices().length;
120994
+ const devices = facade.devices();
120995
+ this.#deviceCount = devices.length;
120996
+ this.#namesAvailable = devices.length === 0 || devices.some((d) => (d.name ?? "").length > 0);
120997
+ if (!this.#namesAvailable) {
120998
+ const credentialsSet = this.#connection.username.length > 0;
120999
+ this.#logger.warn("HmIntegrationManager: device names unavailable — devices are listed by address", {
121000
+ tags: { integrationId: this.#id },
121001
+ meta: {
121002
+ devices: devices.length,
121003
+ credentialsSet,
121004
+ hint: credentialsSet ? "WebUI login set but the CCU returned no names; check the username (an empty password is valid on a CCU without WebUI authentication)" : "set a WebUI username (and password if the CCU has one) on the integration"
121005
+ }
121006
+ });
121007
+ }
120988
121008
  this.#lastCheckedAt = Date.now();
120989
121009
  this.#status = "connected";
120990
121010
  this.#error = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homematic",
3
- "version": "1.2.171",
3
+ "version": "1.2.172",
4
4
  "description": "Homematic / HomematicIP (CCU3 / RaspberryMatic) device-provider addon for CamStack — wraps the nodehomematic library",
5
5
  "keywords": [
6
6
  "camstack",