Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Hardware
  4. MQTT Bluetooth BLE Anwesenheitserkennung mit ESP32

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.7k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.1k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    3.0k

MQTT Bluetooth BLE Anwesenheitserkennung mit ESP32

Geplant Angeheftet Gesperrt Verschoben Hardware
242 Beiträge 26 Kommentatoren 46.0k Aufrufe 32 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • G GiuseppeS

    Bevor hier alle Shelly plus Modelle auf Tasmota geflashed werden:
    Die original Firmware bietet anscheinend auch die Möglichkeit nach ble zu scannen. Bin zufällig drüber gestolpert weil ich gerade alle Shelly zwecks Update durchgegangen bin und ein Skript Beispiel gestoßen bin. Wenn bei den neuen Shellies auf scripts/library geklickt wird, existiert ein Scan Beispiel. Shelly Doku gibt's auch zu dem Punkt:

    https://shelly-api-docs.shelly.cloud/gen2/Scripts/ShellyScriptLanguageFeatures/#blescanner

    Habe selbst weder die Doku gelesen noch das Skript Beispiel getestet. Wenn man aber ein Freund der original Firmware ist (wie ich es bin), wäre das ein möglicher Weg um Tasmota herumzukommen.

    U Offline
    U Offline
    Utze86
    schrieb am zuletzt editiert von
    #163

    @giuseppes da bin ich gestern auch drüber gestolpert. Scheint eine Funktion der neuen Beta zu sein. Werde ich mir auch mal ansehen und würde mir auch entgegenkommen. Dazu muss ich dann aber auch gucken wie ich die beiden Tasmota shellys zurück geflasht bekomme. Bisher habe ich noch keine original shelly Firmware für den Shelly plus 1 gefunden um wieder zurück zu flashen. Bin leider auch im shelly forum bisher noch nicht fündig geworden.

    G 1 Antwort Letzte Antwort
    0
    • U Utze86

      @giuseppes da bin ich gestern auch drüber gestolpert. Scheint eine Funktion der neuen Beta zu sein. Werde ich mir auch mal ansehen und würde mir auch entgegenkommen. Dazu muss ich dann aber auch gucken wie ich die beiden Tasmota shellys zurück geflasht bekomme. Bisher habe ich noch keine original shelly Firmware für den Shelly plus 1 gefunden um wieder zurück zu flashen. Bin leider auch im shelly forum bisher noch nicht fündig geworden.

      G Offline
      G Offline
      GiuseppeS
      schrieb am zuletzt editiert von
      #164

      @utze86
      Ich müsste nur einen Shelly zurück flashen. Habe mich damit aber noch nicht beschäftigt, weil ich erstmal die Machbarkeit analysieren wollte. Eine Sache ist nämlich, die Signale über den Shelly zu empfangen, aber die Daten dann in ioBroker zu bekommen steht woanders geschrieben. Mqtt ist über den Shelly Adapter quasi blockiert. Der Adapter ist jedenfalls nicht für beliebige mqtt topics ausgelegt. D.h. rssi Werte + Standard Steuerung über mqtt ist nicht möglich.
      Was möglich wäre, über Javascript in ioBroker einen outbound websocket laufen zu lassen. Da gibt's auch was von shelly / alterco, habe ich gestern gefunden (auch noch nicht getestet):
      https://github.com/ALLTERCO/shelly-outbound-websockets

      Zum Thema Fingerprint:
      https://synyx.de/blog/fingerprinting-indoor-positionsbestimmung-mit-bluetooth-low-energy-2-2/

      Deine Umsetzungsidee klingt gut. Muss definitiv funktionieren wenn günstig gelegene Shelly für beide Seiten der Wand genutzt werden. Mit den Min UND Max Werte zu arbeiten, statt mit median o.ä. würde definitiv die Trägheit mindern. Die Umsetzung des Algorithmus bei der späteren Standortbestimmung würde mich interessieren.

      Zum Fingerprint habe ich folgende Umsetzung im Kopf:

      • zunächst werden alle Scanner dem System bekannt gemacht.
      • "Neue Position anlegen" wird ausgelöst worauf die gewünschten Scanner ausgewählt werden müssen
      • Anlernvorgang läuft eine gewisse Zeit X, wobei definitiv mehrere Werte je Scanner ermittelt werden müssten. Ermittelte Werte würden gefiltert werden bzw median o.ä. (evtl mit Min und Max Werten aus deinem Vorschlag?).
      • Bei der späteren Auswertung werden alle gespeicherten Positionen durchlaufen und mit den aktuellsten Scannerwerten verglichen. Es werden immer nur die relevanten Scannerwerte der gespeicherten Position betrachtet.

      Hatte es öfters durchgespielt, so umzusetzen wie im obigen link und immer alle Scanner einbeziehen. Aber es könnten mehrere Probleme auftreten. Z.B. was passiert wenn man in der Nähe eines Scanners ist und sich "schnell" wegbewegt, sodass man nicht mehr in Reichweite ist? Der Scanner würde immernoch einen nahen Wert anzeigen und der Timestamp wäre trotzdem nicht älter als 10s.

      Ich würde nur statisch relevante Positionen anlernen. Das wären z.B. Vorzugsplätze am Esstisch, auf der Couch, am Schreibtisch etc.
      Das System schätze ich träge im Bereich von bestimmt 10s ein. Bereiche, wo ich eher durchlaufe sind somit weniger relevant, könnten aber bei Ungenauigkeiten als vermeintlicher Standort ausgewertet werden.

      Mit den Shelly ist es jedenfalls sehr interessant geworden, da somit automatisch viele Scanner zur Verfügung stehen und man nichts mit "nackten" esp32 basteln muss. Steckdosen würden unnötig belegt werden etc.
      Ich teste im nächsten Schritt, wie das mit dem Shelly + WebSocket funktioniert. Es gibt bei den Shelly sogar infinite Scanintervalle. Könnte so sein wie bei espresense, sofort ein Wert wenn der Beacon / die Uhr sendet.

      Zum Thema Beacon: habe neuerdings die Pixel Watch und habe eine apk installiert, die einen Beacon simuliert. Funktioniert auch ganz gut. MAC ist aber dynamisch, daher muss ich auf die UID achten. Mit ESPresense kein Problem, mit Shelly... mal schauen

      U 1 Antwort Letzte Antwort
      0
      • G GiuseppeS

        @utze86
        Ich müsste nur einen Shelly zurück flashen. Habe mich damit aber noch nicht beschäftigt, weil ich erstmal die Machbarkeit analysieren wollte. Eine Sache ist nämlich, die Signale über den Shelly zu empfangen, aber die Daten dann in ioBroker zu bekommen steht woanders geschrieben. Mqtt ist über den Shelly Adapter quasi blockiert. Der Adapter ist jedenfalls nicht für beliebige mqtt topics ausgelegt. D.h. rssi Werte + Standard Steuerung über mqtt ist nicht möglich.
        Was möglich wäre, über Javascript in ioBroker einen outbound websocket laufen zu lassen. Da gibt's auch was von shelly / alterco, habe ich gestern gefunden (auch noch nicht getestet):
        https://github.com/ALLTERCO/shelly-outbound-websockets

        Zum Thema Fingerprint:
        https://synyx.de/blog/fingerprinting-indoor-positionsbestimmung-mit-bluetooth-low-energy-2-2/

        Deine Umsetzungsidee klingt gut. Muss definitiv funktionieren wenn günstig gelegene Shelly für beide Seiten der Wand genutzt werden. Mit den Min UND Max Werte zu arbeiten, statt mit median o.ä. würde definitiv die Trägheit mindern. Die Umsetzung des Algorithmus bei der späteren Standortbestimmung würde mich interessieren.

        Zum Fingerprint habe ich folgende Umsetzung im Kopf:

        • zunächst werden alle Scanner dem System bekannt gemacht.
        • "Neue Position anlegen" wird ausgelöst worauf die gewünschten Scanner ausgewählt werden müssen
        • Anlernvorgang läuft eine gewisse Zeit X, wobei definitiv mehrere Werte je Scanner ermittelt werden müssten. Ermittelte Werte würden gefiltert werden bzw median o.ä. (evtl mit Min und Max Werten aus deinem Vorschlag?).
        • Bei der späteren Auswertung werden alle gespeicherten Positionen durchlaufen und mit den aktuellsten Scannerwerten verglichen. Es werden immer nur die relevanten Scannerwerte der gespeicherten Position betrachtet.

        Hatte es öfters durchgespielt, so umzusetzen wie im obigen link und immer alle Scanner einbeziehen. Aber es könnten mehrere Probleme auftreten. Z.B. was passiert wenn man in der Nähe eines Scanners ist und sich "schnell" wegbewegt, sodass man nicht mehr in Reichweite ist? Der Scanner würde immernoch einen nahen Wert anzeigen und der Timestamp wäre trotzdem nicht älter als 10s.

        Ich würde nur statisch relevante Positionen anlernen. Das wären z.B. Vorzugsplätze am Esstisch, auf der Couch, am Schreibtisch etc.
        Das System schätze ich träge im Bereich von bestimmt 10s ein. Bereiche, wo ich eher durchlaufe sind somit weniger relevant, könnten aber bei Ungenauigkeiten als vermeintlicher Standort ausgewertet werden.

        Mit den Shelly ist es jedenfalls sehr interessant geworden, da somit automatisch viele Scanner zur Verfügung stehen und man nichts mit "nackten" esp32 basteln muss. Steckdosen würden unnötig belegt werden etc.
        Ich teste im nächsten Schritt, wie das mit dem Shelly + WebSocket funktioniert. Es gibt bei den Shelly sogar infinite Scanintervalle. Könnte so sein wie bei espresense, sofort ein Wert wenn der Beacon / die Uhr sendet.

        Zum Thema Beacon: habe neuerdings die Pixel Watch und habe eine apk installiert, die einen Beacon simuliert. Funktioniert auch ganz gut. MAC ist aber dynamisch, daher muss ich auf die UID achten. Mit ESPresense kein Problem, mit Shelly... mal schauen

        U Offline
        U Offline
        Utze86
        schrieb am zuletzt editiert von
        #165

        @giuseppes Thema Fingerprint muss ich mir mal am Wochenende angucken. Was das Thema WebSocket angeht blicke ich tatsächlich überhaupt nicht durch. Ich bin gespannt was du dir überlegst.

        Inzwischen habe ich allerdings ein Eintrag in der englischen Shelly Support Gruppe auf Facebook gefunden der von "Shelly selbst" stammt. Wenn ich das richtig lese gibt es dort ein Script als Beispiel wo ein Sensor per Shelly über BLE ausgelesen wird und das ganze per MQTT übermittelt wird. Lässt sich das für unsere Zwecke anpassen? Der Eintrag ist noch recht frisch:

        https://www.facebook.com/groups/ShellyIoTCommunitySupport/permalink/5383581891741131

        G 1 Antwort Letzte Antwort
        0
        • U Utze86

          @giuseppes Thema Fingerprint muss ich mir mal am Wochenende angucken. Was das Thema WebSocket angeht blicke ich tatsächlich überhaupt nicht durch. Ich bin gespannt was du dir überlegst.

          Inzwischen habe ich allerdings ein Eintrag in der englischen Shelly Support Gruppe auf Facebook gefunden der von "Shelly selbst" stammt. Wenn ich das richtig lese gibt es dort ein Script als Beispiel wo ein Sensor per Shelly über BLE ausgelesen wird und das ganze per MQTT übermittelt wird. Lässt sich das für unsere Zwecke anpassen? Der Eintrag ist noch recht frisch:

          https://www.facebook.com/groups/ShellyIoTCommunitySupport/permalink/5383581891741131

          G Offline
          G Offline
          GiuseppeS
          schrieb am zuletzt editiert von GiuseppeS
          #166

          @utze86
          Habe mir das eben in den Werbepausen auf dem Handy angeschaut und bisschen mit dem Skript getestet. Du kannst das original Skript direkt im Shelly laden, über Scripts/Library kannst du es wählen.
          Mit fixer MAC hatte es einwandfrei geklappt, ausschließlich MAC + RSSI auszugeben. Damit mein ich die Ausgabe innerhalb der Konsole der Shelly Web Oberfläche. Ich teste(te) gerade noch wie ich die UUID eines Beacon auslesen kann. Habe hierzu noch keine Lösung, aber es sollte funktionieren.
          Auf jeden Fall konnte ich sehen, dass das kontinuierliche Scannen anscheinend super klappt. Verschiedene Geräte wurden mehrfach innerhalb weniger Sekunden erfasst.
          Bzgl Shelly wäre also noch offen, wie ich auf die UUID vom BLE Gerät zugreifen kann und die Übertragung zu ioBroker (websocket oder outbound websocket).

          Da das Auslesen der UUID noch etwas dauern kann, werde ich versuchen zeitnah die Übertragung zu ioBroker umzusetzen. Könnte dann die paar Zeilen hier teilen. Dann könntest du mit der Mi Band schon etwas weiter testen. Werde hoffentlich dieses Wochenende Zeit dafür finden. Bin selbst auch neugierig, wie gut alles klappt.

          U 1 Antwort Letzte Antwort
          0
          • G GiuseppeS

            @utze86
            Habe mir das eben in den Werbepausen auf dem Handy angeschaut und bisschen mit dem Skript getestet. Du kannst das original Skript direkt im Shelly laden, über Scripts/Library kannst du es wählen.
            Mit fixer MAC hatte es einwandfrei geklappt, ausschließlich MAC + RSSI auszugeben. Damit mein ich die Ausgabe innerhalb der Konsole der Shelly Web Oberfläche. Ich teste(te) gerade noch wie ich die UUID eines Beacon auslesen kann. Habe hierzu noch keine Lösung, aber es sollte funktionieren.
            Auf jeden Fall konnte ich sehen, dass das kontinuierliche Scannen anscheinend super klappt. Verschiedene Geräte wurden mehrfach innerhalb weniger Sekunden erfasst.
            Bzgl Shelly wäre also noch offen, wie ich auf die UUID vom BLE Gerät zugreifen kann und die Übertragung zu ioBroker (websocket oder outbound websocket).

            Da das Auslesen der UUID noch etwas dauern kann, werde ich versuchen zeitnah die Übertragung zu ioBroker umzusetzen. Könnte dann die paar Zeilen hier teilen. Dann könntest du mit der Mi Band schon etwas weiter testen. Werde hoffentlich dieses Wochenende Zeit dafür finden. Bin selbst auch neugierig, wie gut alles klappt.

            U Offline
            U Offline
            Utze86
            schrieb am zuletzt editiert von
            #167

            @giuseppes klingt sehr vielversprechend, ich werde die Tage auch mal etwas mit Script spielen und bin gespannt was du noch so raus bekommst. Leider kann ich nicht immer so viel dazu beitragen, da ich mich mit dem programmieren etwas schwer tuhe. Meist bin ich mit Blockly unterwegs. Aber mit viel fummelei bekomme ich die meisten Sachen für mich adaptiert. Und werde natürlich auch die Lösung bezüglich meiner Schnittflächen hier teilen. Ich bin gespannt wie es funktioniert.

            Was versprichst du dir von dem auslesen der UUID, bzw. Wofür ist das wichtig? Für die Zuordnung der unterschiedlichen Geräte oder wobei kann das helfen?

            G 1 Antwort Letzte Antwort
            0
            • U Utze86

              @giuseppes klingt sehr vielversprechend, ich werde die Tage auch mal etwas mit Script spielen und bin gespannt was du noch so raus bekommst. Leider kann ich nicht immer so viel dazu beitragen, da ich mich mit dem programmieren etwas schwer tuhe. Meist bin ich mit Blockly unterwegs. Aber mit viel fummelei bekomme ich die meisten Sachen für mich adaptiert. Und werde natürlich auch die Lösung bezüglich meiner Schnittflächen hier teilen. Ich bin gespannt wie es funktioniert.

              Was versprichst du dir von dem auslesen der UUID, bzw. Wofür ist das wichtig? Für die Zuordnung der unterschiedlichen Geräte oder wobei kann das helfen?

              G Offline
              G Offline
              GiuseppeS
              schrieb am zuletzt editiert von
              #168

              @utze86
              Android Smartphones und auch meine Pixel Watch können mit Hilfe von Apps iBeacon simulieren und somit BLE advertisements senden. Aber die MAC ist leider nicht konstant, das lässt das Betriebssystem nicht zu. Ähnlich ist es ja auch bei Apple Geräten. Was aber zumindest bei den Android Apps konstant bleibt, das ist die UUID, die mitgesendet wird. Espresense bildet seine Gerätenamen auch entweder mit MAC oder den UUID. Mi Band sendet immer mit selber MAC, somit brauchst du das das mit der UUID nicht.

              1 Antwort Letzte Antwort
              0
              • G Offline
                G Offline
                GiuseppeS
                schrieb am zuletzt editiert von GiuseppeS
                #169

                Aus dem ganzen BLE code vom Beispielskript ist eigentlich nur das notwendig:

                function scanCB(ev, res) {
                    if (ev === BLE.Scanner.SCAN_RESULT) {
                        
                        let StaticMAC = { "addr": res.addr.slice(0,-2), "rssi": res.rssi };
                        
                        //print( JSON.stringify(StaticMAC));
                        Shelly.emitEvent( "ShellyScanresult", StaticMAC);
                    }
                }
                
                BLE.Scanner.Start({ duration_ms: -1}, scanCB);
                

                Über die Websocket Verbindung wird dann MAC und RSSI ausgegeben. Ich wollte eben den Outbound server von Shelly in iobroker einbinden. Dabei ist mir aber aufgefallen, dass das letzte ALexa Update einige meiner Skripte zerschossen hat. Bedeutet, die Websocket Seite von iobroker aus steht noch nicht.

                Habe übrigens die Scan-Aktivitäten vom Shelly mit meinem Mi Band 6 getestet (habe ich ja noch daheim). Das Band wurde kontinuierlich alle 9 Sekunden empfangen. ESPresense empfängt alle 5 Sekunden. Evtl müsste man an den Scaneinstellungen vom Shelly optimieren. Aktuell steht es auf Infinite Scan, hätte eigentlich das Optimum sein sollen...

                1 Antwort Letzte Antwort
                0
                • G Offline
                  G Offline
                  GiuseppeS
                  schrieb am zuletzt editiert von
                  #170

                  Habe noch etwas weiter getestet:

                  Das war nun als Skript zuletzt im Shelly im Einsatz gewesen:

                  function scanCB(ev, res) {
                      if (ev === BLE.Scanner.SCAN_RESULT) {
                          let mac = res.addr.slice(0,-2);
                          
                          //if ( mac === "e8:61:51:5f:f0:2e"){
                            let StaticMAC = { "addr": res.addr.slice(0,-2), "rssi": res.rssi };
                            //print( JSON.stringify(StaticMAC));
                            Shelly.emitEvent( "ShellyScanresult", StaticMAC);
                          //}
                      }
                  }
                  
                  BLE.Scanner.Start({ duration_ms: -1}, scanCB);
                  

                  Hatte mit der if-Bedingung einen Filter auf meine MiBand MAC verwendet.

                  Im Shelly muss bei "Settings/Connectivity/Outbound Websocket" die IP von iobroker mit Port 8085 eingegeben werden. Bei mir sah das so aus:
                  394012e7-3e79-478e-921f-c5b1abd7a42c-image.png

                  Mein iobroker Skript:

                  const {WebSocketServer, WebSocket} = require('ws');
                  
                  const port = 8085;
                  const DEBUG = true;
                  
                  /**
                   * Simple object check.
                   * @param item
                   * @returns {boolean}
                   */
                  function isObject(item) {
                      return (item && typeof item === 'object' && !Array.isArray(item));
                  }
                  
                  /**
                   * Deep merge two objects.
                   * @param target
                   * @param ...sources
                   */
                  function mergeDeep(target, ...sources) {
                      if (!sources.length) return target;
                      const source = sources.shift();
                  
                      if (isObject(target) && isObject(source)) {
                          for (const key in source) {
                              if (isObject(source[key])) {
                                  if (!target[key]) Object.assign(target, { [key]: {} });
                                  mergeDeep(target[key], source[key]);
                              } else {
                                  Object.assign(target, { [key]: source[key] });
                              }
                          }
                      }
                  
                      return mergeDeep(target, ...sources);
                  }
                  
                  /**
                   * Shelly Outbound WebSocket
                   */
                  class ShellyOWS {
                      handlers = {};
                      _idx = 0;
                      httpServer = null;
                      _clients = {};
                      _statuses = {};
                      _config = {};
                      _requests = {};
                      ws = null;
                  
                      /**
                       * Init ShellyOWS with an existing httpServer
                       *
                       * @param {http.Server} httpServer
                       */
                      constructor(httpServer) {
                          this.httpServer = httpServer;
                  
                          this.init();
                      }
                  
                      /**
                       * Internal method that is called in constructor to initialize
                       *
                       * @private
                       */
                      init() {
                          this.ws = new WebSocketServer({server: this.httpServer});
                          this.ws.on('connection', async (webSocket, request, client) => {
                              if (DEBUG) {
                                  console.warn('New connection: ', request.socket.remoteAddress);
                              }
                  
                              webSocket.on('message', async (message) => {
                                  message = JSON.parse(message.toString());
                  
                                  this._clients[message.src] = webSocket;
                                  webSocket.clientId = message.src;
                  
                                  let [model, deviceId] = message.src.split("-");
                  
                                  if (message.method) {
                                      let method = message.method;
                                      let params = message.params;
                                      // console.log('New message', message, model, deviceId, method, params);
                  
                                      if (method === "NotifyFullStatus") {
                                          this._statuses[message.src] = params;
                                          let allConfig = await this.call(message.src, "Shelly.getconfig");
                                          // console.error("allConfig", allConfig);
                                          this._config[message.src] = allConfig;
                                      }
                                      else if (method === "NotifyStatus") {
                                          this._statuses[message.src] = mergeDeep(this._statuses[message.src] || {}, params);
                                      }
                                      else if (method === "NotifyEvent") {
                                          for (let event of params.events) {
                                              if (event.event === "config_changed") {
                                                  let config = await this.call(message.src, event.component + ".getconfig");
                                                  // console.error("updated config:", config);
                                                  this._config[message.src][event.component] = config;
                                              }
                                          }
                                      }
                  
                  
                                      // proceed to call handlers
                                      if (this.handlers[method]) {
                                          this._callHandler(method, message.src, params, webSocket);
                                      }
                                  }
                                  else if (message.result) {
                                      if (message.id && this._requests[message.id]) {
                                          this._requests[message.id](message.result);
                                      }
                                      // TODO: log error/warning?
                                  }
                              });
                  
                              await this.call(webSocket, "shelly.getdeviceinfo");
                  
                              // console.error("new connection", request.socket.remoteAddress);
                          });
                          this.ws.on('close', (webSocket) => {
                              this._callHandler("OWS::Disconnected", webSocket.clientId, undefined, webSocket);
                              delete this._clients[webSocket.clientId];
                          })
                      }
                  
                      /**
                       * Internal.
                       *
                       * @param {string} method
                       * @param {string} id
                       * @param {Object} params
                       * @param {WebSocket} webSocket
                       * @private
                       */
                      _callHandler(method, id, params, webSocket) {
                          if (this.handlers[method]) {
                              let [model, deviceId] = id.split("-");
                  
                              for (let k of Object.keys(this.handlers[method])) {
                                  let cb = this.handlers[method][k];
                  
                                  try {
                                      cb.call(this, id, params, webSocket, model, deviceId);
                                  } catch (ex) {
                                      console.error("Handler", method, 'thrown error:', ex);
                                  }
                              }
                          }
                      }
                  
                      /**
                       * Add new handler
                       *
                       * @param {string} method
                       * @param {Function} cb
                       * @returns {number} ID of the handler, that can be used later with `removeHandler`
                       */
                      addHandler(method, cb) {
                          let id = this._idx++;
                          if (!this.handlers[method]) {
                              this.handlers[method] = {};
                          }
                          this.handlers[method][id] = cb;
                          return id;
                      }
                  
                      /**
                       * Remove handler
                       *
                       * @param {string} method
                       * @param {number} id
                       */
                      removeHandler(method, id) {
                          delete this.handlers[method][id];
                      }
                  
                      /**
                       * Call a RPC on a target device id OR webSocket directly
                       *
                       * @param {string|WebSocket} deviceIdOrWebSocket
                       * @param {string} method
                       * @param {Object} params
                       * @returns {Promise<never>|Promise<unknown>}
                       */
                      call(deviceIdOrWebSocket, method, params) {
                          let webSocket = deviceIdOrWebSocket instanceof WebSocket ?
                              deviceIdOrWebSocket : this._clients[deviceIdOrWebSocket];
                  
                          if (!webSocket) {
                              // console.error(this._clients);
                              return Promise.reject(404);
                          }
                  
                          return new Promise((res, rej) => {
                              let id = this._idx++;
                              this._requests[id] = (response) => {
                                  res(response);
                              };
                              // todo: timeout
                  
                              let req = {"jsonrpc":"2.0", "id": id, "src":"wsserver", "method": method};
                              if (params) {
                                  req['params'] = params;
                              }
                              // console.debug("Calling:", deviceId, req);
                              webSocket.send(JSON.stringify(req));
                          });
                      }
                  
                      /**
                       * Return current (in-memory cached) device status
                       *
                       * @param {string} clientId
                       * @returns {*|{}}
                       */
                      getState(clientId) {
                         return this._statuses[clientId] || {};
                      }
                  
                      /**
                       * Return current (in-memory cached) device config
                       *
                       * @param {string} clientId
                       * @returns {*|{}}
                       */
                      getConfig(clientId) {
                          return this._config[clientId] || {};
                      }
                  
                      /**
                       * Update config (also updates local cache)
                       *
                       * @param {string} clientId
                       * @param {string} component
                       * @param {Object} config
                       * @returns {Promise<*>}
                       */
                      async setConfig(clientId, component, config) {
                          // Since response is returned before the notification, we need to sync our local config first, so that immediate
                          // access to config would return the updated data.
                          //
                          // If you don't want that to happen, feel free to .call Component.SetConfig directly.
                  
                          component = component.toLowerCase();
                  
                          await this.call(clientId, component + ".setconfig", {'config': config});
                  
                          this._config[clientId][component] = mergeDeep(this._config[clientId][component] || {}, config);
                          return this._config[clientId][component];
                      }
                  
                      /**
                       * Return ids of all clients currently connected.
                       *
                       * @returns {string[]}
                       */
                      getClients() {
                          return Object.keys(this._clients);
                      }
                  }
                  
                  
                  /**
                   * ########################################################################################################################
                   * ########################################################################################################################
                   * ########################################################################################################################
                   *  Merge from Server and Script  from page: https://github.com/ALLTERCO/shelly-outbound-websockets
                   * ########################################################################################################################
                   * ########################################################################################################################
                   * ########################################################################################################################
                   */
                  
                  /**
                   * Example on how to use events from 1 device and then toggle other devices.
                   */
                  
                  
                  const http = require('http')
                  
                  console.log('WS server starting at port ' + port);
                  
                  const httpServer = http.createServer()
                  
                  let shellyOws = new ShellyOWS(httpServer);
                  
                  
                  let idHandler = shellyOws.addHandler("NotifyEvent", async (clientId, params) => {
                      console.log( params)
                  });
                  
                  
                  httpServer.listen( port);
                  
                  
                  
                  
                  function closeWS() {
                  
                      //cl( shellyOws.getClients() );
                  
                      console.log("Close http server connection.");
                      shellyOws.removeHandler( "NotifyEvent", idHandler);
                      
                      httpServer.close();
                  }
                  onStop(closeWS, 1000);
                  
                  

                  Ich muss noch herausfinden, wie ich die Verbindung in iobroker zu 100% trenne. Kam jetzt noch nicht dazu. Wenn du das Skript stoppst musst du aktuell die Instanz neu starten, damit der Shelly merkt, dass da keine Gegenseite zuhört. Daher würde ich aktuell eine zusätzliche Instanz zum Testen empfehlen.

                  U 1 Antwort Letzte Antwort
                  0
                  • G GiuseppeS

                    Habe noch etwas weiter getestet:

                    Das war nun als Skript zuletzt im Shelly im Einsatz gewesen:

                    function scanCB(ev, res) {
                        if (ev === BLE.Scanner.SCAN_RESULT) {
                            let mac = res.addr.slice(0,-2);
                            
                            //if ( mac === "e8:61:51:5f:f0:2e"){
                              let StaticMAC = { "addr": res.addr.slice(0,-2), "rssi": res.rssi };
                              //print( JSON.stringify(StaticMAC));
                              Shelly.emitEvent( "ShellyScanresult", StaticMAC);
                            //}
                        }
                    }
                    
                    BLE.Scanner.Start({ duration_ms: -1}, scanCB);
                    

                    Hatte mit der if-Bedingung einen Filter auf meine MiBand MAC verwendet.

                    Im Shelly muss bei "Settings/Connectivity/Outbound Websocket" die IP von iobroker mit Port 8085 eingegeben werden. Bei mir sah das so aus:
                    394012e7-3e79-478e-921f-c5b1abd7a42c-image.png

                    Mein iobroker Skript:

                    const {WebSocketServer, WebSocket} = require('ws');
                    
                    const port = 8085;
                    const DEBUG = true;
                    
                    /**
                     * Simple object check.
                     * @param item
                     * @returns {boolean}
                     */
                    function isObject(item) {
                        return (item && typeof item === 'object' && !Array.isArray(item));
                    }
                    
                    /**
                     * Deep merge two objects.
                     * @param target
                     * @param ...sources
                     */
                    function mergeDeep(target, ...sources) {
                        if (!sources.length) return target;
                        const source = sources.shift();
                    
                        if (isObject(target) && isObject(source)) {
                            for (const key in source) {
                                if (isObject(source[key])) {
                                    if (!target[key]) Object.assign(target, { [key]: {} });
                                    mergeDeep(target[key], source[key]);
                                } else {
                                    Object.assign(target, { [key]: source[key] });
                                }
                            }
                        }
                    
                        return mergeDeep(target, ...sources);
                    }
                    
                    /**
                     * Shelly Outbound WebSocket
                     */
                    class ShellyOWS {
                        handlers = {};
                        _idx = 0;
                        httpServer = null;
                        _clients = {};
                        _statuses = {};
                        _config = {};
                        _requests = {};
                        ws = null;
                    
                        /**
                         * Init ShellyOWS with an existing httpServer
                         *
                         * @param {http.Server} httpServer
                         */
                        constructor(httpServer) {
                            this.httpServer = httpServer;
                    
                            this.init();
                        }
                    
                        /**
                         * Internal method that is called in constructor to initialize
                         *
                         * @private
                         */
                        init() {
                            this.ws = new WebSocketServer({server: this.httpServer});
                            this.ws.on('connection', async (webSocket, request, client) => {
                                if (DEBUG) {
                                    console.warn('New connection: ', request.socket.remoteAddress);
                                }
                    
                                webSocket.on('message', async (message) => {
                                    message = JSON.parse(message.toString());
                    
                                    this._clients[message.src] = webSocket;
                                    webSocket.clientId = message.src;
                    
                                    let [model, deviceId] = message.src.split("-");
                    
                                    if (message.method) {
                                        let method = message.method;
                                        let params = message.params;
                                        // console.log('New message', message, model, deviceId, method, params);
                    
                                        if (method === "NotifyFullStatus") {
                                            this._statuses[message.src] = params;
                                            let allConfig = await this.call(message.src, "Shelly.getconfig");
                                            // console.error("allConfig", allConfig);
                                            this._config[message.src] = allConfig;
                                        }
                                        else if (method === "NotifyStatus") {
                                            this._statuses[message.src] = mergeDeep(this._statuses[message.src] || {}, params);
                                        }
                                        else if (method === "NotifyEvent") {
                                            for (let event of params.events) {
                                                if (event.event === "config_changed") {
                                                    let config = await this.call(message.src, event.component + ".getconfig");
                                                    // console.error("updated config:", config);
                                                    this._config[message.src][event.component] = config;
                                                }
                                            }
                                        }
                    
                    
                                        // proceed to call handlers
                                        if (this.handlers[method]) {
                                            this._callHandler(method, message.src, params, webSocket);
                                        }
                                    }
                                    else if (message.result) {
                                        if (message.id && this._requests[message.id]) {
                                            this._requests[message.id](message.result);
                                        }
                                        // TODO: log error/warning?
                                    }
                                });
                    
                                await this.call(webSocket, "shelly.getdeviceinfo");
                    
                                // console.error("new connection", request.socket.remoteAddress);
                            });
                            this.ws.on('close', (webSocket) => {
                                this._callHandler("OWS::Disconnected", webSocket.clientId, undefined, webSocket);
                                delete this._clients[webSocket.clientId];
                            })
                        }
                    
                        /**
                         * Internal.
                         *
                         * @param {string} method
                         * @param {string} id
                         * @param {Object} params
                         * @param {WebSocket} webSocket
                         * @private
                         */
                        _callHandler(method, id, params, webSocket) {
                            if (this.handlers[method]) {
                                let [model, deviceId] = id.split("-");
                    
                                for (let k of Object.keys(this.handlers[method])) {
                                    let cb = this.handlers[method][k];
                    
                                    try {
                                        cb.call(this, id, params, webSocket, model, deviceId);
                                    } catch (ex) {
                                        console.error("Handler", method, 'thrown error:', ex);
                                    }
                                }
                            }
                        }
                    
                        /**
                         * Add new handler
                         *
                         * @param {string} method
                         * @param {Function} cb
                         * @returns {number} ID of the handler, that can be used later with `removeHandler`
                         */
                        addHandler(method, cb) {
                            let id = this._idx++;
                            if (!this.handlers[method]) {
                                this.handlers[method] = {};
                            }
                            this.handlers[method][id] = cb;
                            return id;
                        }
                    
                        /**
                         * Remove handler
                         *
                         * @param {string} method
                         * @param {number} id
                         */
                        removeHandler(method, id) {
                            delete this.handlers[method][id];
                        }
                    
                        /**
                         * Call a RPC on a target device id OR webSocket directly
                         *
                         * @param {string|WebSocket} deviceIdOrWebSocket
                         * @param {string} method
                         * @param {Object} params
                         * @returns {Promise<never>|Promise<unknown>}
                         */
                        call(deviceIdOrWebSocket, method, params) {
                            let webSocket = deviceIdOrWebSocket instanceof WebSocket ?
                                deviceIdOrWebSocket : this._clients[deviceIdOrWebSocket];
                    
                            if (!webSocket) {
                                // console.error(this._clients);
                                return Promise.reject(404);
                            }
                    
                            return new Promise((res, rej) => {
                                let id = this._idx++;
                                this._requests[id] = (response) => {
                                    res(response);
                                };
                                // todo: timeout
                    
                                let req = {"jsonrpc":"2.0", "id": id, "src":"wsserver", "method": method};
                                if (params) {
                                    req['params'] = params;
                                }
                                // console.debug("Calling:", deviceId, req);
                                webSocket.send(JSON.stringify(req));
                            });
                        }
                    
                        /**
                         * Return current (in-memory cached) device status
                         *
                         * @param {string} clientId
                         * @returns {*|{}}
                         */
                        getState(clientId) {
                           return this._statuses[clientId] || {};
                        }
                    
                        /**
                         * Return current (in-memory cached) device config
                         *
                         * @param {string} clientId
                         * @returns {*|{}}
                         */
                        getConfig(clientId) {
                            return this._config[clientId] || {};
                        }
                    
                        /**
                         * Update config (also updates local cache)
                         *
                         * @param {string} clientId
                         * @param {string} component
                         * @param {Object} config
                         * @returns {Promise<*>}
                         */
                        async setConfig(clientId, component, config) {
                            // Since response is returned before the notification, we need to sync our local config first, so that immediate
                            // access to config would return the updated data.
                            //
                            // If you don't want that to happen, feel free to .call Component.SetConfig directly.
                    
                            component = component.toLowerCase();
                    
                            await this.call(clientId, component + ".setconfig", {'config': config});
                    
                            this._config[clientId][component] = mergeDeep(this._config[clientId][component] || {}, config);
                            return this._config[clientId][component];
                        }
                    
                        /**
                         * Return ids of all clients currently connected.
                         *
                         * @returns {string[]}
                         */
                        getClients() {
                            return Object.keys(this._clients);
                        }
                    }
                    
                    
                    /**
                     * ########################################################################################################################
                     * ########################################################################################################################
                     * ########################################################################################################################
                     *  Merge from Server and Script  from page: https://github.com/ALLTERCO/shelly-outbound-websockets
                     * ########################################################################################################################
                     * ########################################################################################################################
                     * ########################################################################################################################
                     */
                    
                    /**
                     * Example on how to use events from 1 device and then toggle other devices.
                     */
                    
                    
                    const http = require('http')
                    
                    console.log('WS server starting at port ' + port);
                    
                    const httpServer = http.createServer()
                    
                    let shellyOws = new ShellyOWS(httpServer);
                    
                    
                    let idHandler = shellyOws.addHandler("NotifyEvent", async (clientId, params) => {
                        console.log( params)
                    });
                    
                    
                    httpServer.listen( port);
                    
                    
                    
                    
                    function closeWS() {
                    
                        //cl( shellyOws.getClients() );
                    
                        console.log("Close http server connection.");
                        shellyOws.removeHandler( "NotifyEvent", idHandler);
                        
                        httpServer.close();
                    }
                    onStop(closeWS, 1000);
                    
                    

                    Ich muss noch herausfinden, wie ich die Verbindung in iobroker zu 100% trenne. Kam jetzt noch nicht dazu. Wenn du das Skript stoppst musst du aktuell die Instanz neu starten, damit der Shelly merkt, dass da keine Gegenseite zuhört. Daher würde ich aktuell eine zusätzliche Instanz zum Testen empfehlen.

                    U Offline
                    U Offline
                    Utze86
                    schrieb am zuletzt editiert von
                    #171

                    @giuseppes ja cool, danke! Werde ich testen sobald es geht. Leider bin ich diese Woche wieder unterwegs, daher muss das leider wieder bis zum Wochende warten :-(

                    G 1 Antwort Letzte Antwort
                    0
                    • U Utze86

                      @giuseppes ja cool, danke! Werde ich testen sobald es geht. Leider bin ich diese Woche wieder unterwegs, daher muss das leider wieder bis zum Wochende warten :-(

                      G Offline
                      G Offline
                      GiuseppeS
                      schrieb am zuletzt editiert von
                      #172

                      @utze86
                      Habe unter der Woche auch immer weniger Zeit. Aber heute wollte ich zumindest das saubere Beenden des Skripts schaffen. Das klappt jetzt. Werde, sobald möglich, dass automatische Erstellen der States hinzufügen. Dann ist es für den ersten Beta-Test ausreichend. Ich bin weiterhin nicht überzeugt, ob die original Firmware "so gut" scannt, wie es Tasmota macht.

                      U 1 Antwort Letzte Antwort
                      0
                      • G GiuseppeS

                        @utze86
                        Habe unter der Woche auch immer weniger Zeit. Aber heute wollte ich zumindest das saubere Beenden des Skripts schaffen. Das klappt jetzt. Werde, sobald möglich, dass automatische Erstellen der States hinzufügen. Dann ist es für den ersten Beta-Test ausreichend. Ich bin weiterhin nicht überzeugt, ob die original Firmware "so gut" scannt, wie es Tasmota macht.

                        U Offline
                        U Offline
                        Utze86
                        schrieb am zuletzt editiert von
                        #173

                        @giuseppes So ich hatte am Wochenende mal wieder etwas Zeit zum testen. Was Tasmota angeht habe ich mich durch mehrere Intervalle durchprobiert.

                        Erkenntnis: Es lassen sich auch Intervalle mit halben Sekunden abfragen. Jede Sekunde abfragen liefert bei mir bisher das beste Ergebnis. Im Durchschnitt erhalte ich alle 2,5 Sekunden ein Signal von meinem Mi Band 4, oftmals auch jede Sekunde. Zumindest gibt dies die Konsole des Shelly wieder.

                        Anschließend habe ich die Shelly Beta Firmware getestet um zu gucken mit welcher Firmware ich das bessere Ergebnis erziele. Die BLE Auswertung am Shelly funktioniert schonmal super. Auch mit deinem Skript werden die Werte im iobroker ausgelesen. Allerdings ist mir nicht klar, ob und in welchen Datenpunkt die RSSI Werte im iobroker geschrieben werden. Hast du hier eine Idee? Mit den Werten würde ich dann die weitere Verarbeitung in Blockly durchführen wollen. Weiter hat mich etwas stutzig gemacht, dass die MAC Adressen die ausgelesen werden nur 10 Stellig sind, zumindest laut Log. Sollten die Adressen nicht 12 Stellig sein? Mein Mi Band konnte ich so leider nicht auf anhieb finden, allerdings war der Akku des Armbands fast leer, eventuell hat es daher nicht gesendet. Ich müsste das in den nächsten Tagen nochmal prüfen.

                        Wenn das ganze funktioniert werde ich ziemlich gut abschätzen können welche Firmware für mich das bessere Ergebnis liefert. Ich hoffe ebenfalls, dass ich auf die Shelly Firmware zurückgreifen kann. Das würde einiges einfacher machen.

                        Wie kommst du mit dem Skript voran? Gibt es bereits Neuigkeiten?

                        VG Utze

                        G 2 Antworten Letzte Antwort
                        0
                        • U Utze86

                          @giuseppes So ich hatte am Wochenende mal wieder etwas Zeit zum testen. Was Tasmota angeht habe ich mich durch mehrere Intervalle durchprobiert.

                          Erkenntnis: Es lassen sich auch Intervalle mit halben Sekunden abfragen. Jede Sekunde abfragen liefert bei mir bisher das beste Ergebnis. Im Durchschnitt erhalte ich alle 2,5 Sekunden ein Signal von meinem Mi Band 4, oftmals auch jede Sekunde. Zumindest gibt dies die Konsole des Shelly wieder.

                          Anschließend habe ich die Shelly Beta Firmware getestet um zu gucken mit welcher Firmware ich das bessere Ergebnis erziele. Die BLE Auswertung am Shelly funktioniert schonmal super. Auch mit deinem Skript werden die Werte im iobroker ausgelesen. Allerdings ist mir nicht klar, ob und in welchen Datenpunkt die RSSI Werte im iobroker geschrieben werden. Hast du hier eine Idee? Mit den Werten würde ich dann die weitere Verarbeitung in Blockly durchführen wollen. Weiter hat mich etwas stutzig gemacht, dass die MAC Adressen die ausgelesen werden nur 10 Stellig sind, zumindest laut Log. Sollten die Adressen nicht 12 Stellig sein? Mein Mi Band konnte ich so leider nicht auf anhieb finden, allerdings war der Akku des Armbands fast leer, eventuell hat es daher nicht gesendet. Ich müsste das in den nächsten Tagen nochmal prüfen.

                          Wenn das ganze funktioniert werde ich ziemlich gut abschätzen können welche Firmware für mich das bessere Ergebnis liefert. Ich hoffe ebenfalls, dass ich auf die Shelly Firmware zurückgreifen kann. Das würde einiges einfacher machen.

                          Wie kommst du mit dem Skript voran? Gibt es bereits Neuigkeiten?

                          VG Utze

                          G Offline
                          G Offline
                          GiuseppeS
                          schrieb am zuletzt editiert von
                          #174

                          @utze86
                          Das Shelly Skript ist nach aktuellem Stand nicht mehr aktuell. Mit der Shelly beta2 hat sich die Struktur geändert, u.a. wurde die MAC angepasst, deshalb fehlen nun zwei Stellen.

                          Tasmota hatte mit meinen letzten Tests definitiv bessere Scan Ergebnisse. Deine Werte von 2-3 Sekunden sind schon richtig top. Ich musste aber heute meinen verbauten Tasmota Shelly ausbauen. Der Schaltzustand von meinem detached Schalter wurde sehr spät erkannt / übertragen. Daher tendiere ich nun noch mehr zur Shelly Firmware. Hier sollte aber der finale Stand abgewartet werden, sonst skripted man mehrfach.
                          In meinem ioBroker Skript für Shelly (websocket server) ist noch kein Schreiben in States integriert. Müsste ich ergänzen. Allerdings hatte ich zuletzt meine paar freien Stunden in eine Wegmessung meines elektrisch verstellbaren Schreibtisches investiert. Habe ich heute abgeschlossen und werde mich wieder um dieses Thema kümmern ;-)

                          1 Antwort Letzte Antwort
                          0
                          • U Utze86

                            @giuseppes So ich hatte am Wochenende mal wieder etwas Zeit zum testen. Was Tasmota angeht habe ich mich durch mehrere Intervalle durchprobiert.

                            Erkenntnis: Es lassen sich auch Intervalle mit halben Sekunden abfragen. Jede Sekunde abfragen liefert bei mir bisher das beste Ergebnis. Im Durchschnitt erhalte ich alle 2,5 Sekunden ein Signal von meinem Mi Band 4, oftmals auch jede Sekunde. Zumindest gibt dies die Konsole des Shelly wieder.

                            Anschließend habe ich die Shelly Beta Firmware getestet um zu gucken mit welcher Firmware ich das bessere Ergebnis erziele. Die BLE Auswertung am Shelly funktioniert schonmal super. Auch mit deinem Skript werden die Werte im iobroker ausgelesen. Allerdings ist mir nicht klar, ob und in welchen Datenpunkt die RSSI Werte im iobroker geschrieben werden. Hast du hier eine Idee? Mit den Werten würde ich dann die weitere Verarbeitung in Blockly durchführen wollen. Weiter hat mich etwas stutzig gemacht, dass die MAC Adressen die ausgelesen werden nur 10 Stellig sind, zumindest laut Log. Sollten die Adressen nicht 12 Stellig sein? Mein Mi Band konnte ich so leider nicht auf anhieb finden, allerdings war der Akku des Armbands fast leer, eventuell hat es daher nicht gesendet. Ich müsste das in den nächsten Tagen nochmal prüfen.

                            Wenn das ganze funktioniert werde ich ziemlich gut abschätzen können welche Firmware für mich das bessere Ergebnis liefert. Ich hoffe ebenfalls, dass ich auf die Shelly Firmware zurückgreifen kann. Das würde einiges einfacher machen.

                            Wie kommst du mit dem Skript voran? Gibt es bereits Neuigkeiten?

                            VG Utze

                            G Offline
                            G Offline
                            GiuseppeS
                            schrieb am zuletzt editiert von GiuseppeS
                            #175

                            @utze86

                            Habe nun das Skript überarbeitet, sodass die RSSI Werte in States geschrieben werden. Anbei die aktuellen Stände:

                            Skript Shelly:

                            function scanCB(ev, res) {
                                if (ev === BLE.Scanner.SCAN_RESULT) {
                                    let mac = res.addr;
                                    let rssi = res.rssi;
                                    let macType = res.addr_type;
                                    
                                    //print( JSON.stringify( res));
                                    
                                    if ( macType < 3){
                                      let JsonMsg = { "addr": mac, "rssi": rssi };
                                      //print(JSON.stringify( JsonMsg) );
                                      Shelly.emitEvent( "ShellyScanresult", JsonMsg);
                                    }
                                }
                            }
                            
                            BLE.Scanner.Start({ duration_ms: -1}, scanCB);
                            

                            Skript iobroker:

                            const {WebSocketServer, WebSocket} = require('ws');
                            
                            const port = 8085;
                            
                            const DEBUG = false;
                            
                            /**
                             * Simple object check.
                             * @param item
                             * @returns {boolean}
                             */
                            function isObject(item) {
                                return (item && typeof item === 'object' && !Array.isArray(item));
                            }
                            
                            /**
                             * Deep merge two objects.
                             * @param target
                             * @param ...sources
                             */
                            function mergeDeep(target, ...sources) {
                                if (!sources.length) return target;
                                const source = sources.shift();
                            
                                if (isObject(target) && isObject(source)) {
                                    for (const key in source) {
                                        if (isObject(source[key])) {
                                            if (!target[key]) Object.assign(target, { [key]: {} });
                                            mergeDeep(target[key], source[key]);
                                        } else {
                                            Object.assign(target, { [key]: source[key] });
                                        }
                                    }
                                }
                            
                                return mergeDeep(target, ...sources);
                            }
                            
                            /**
                             * Shelly Outbound WebSocket
                             */
                            class ShellyOWS {
                                handlers = {};
                                _idx = 0;
                                httpServer = null;
                                _clients = {};
                                _statuses = {};
                                _config = {};
                                _requests = {};
                                ws = null;
                                sockets = [];
                            
                                /**
                                 * Init ShellyOWS with an existing httpServer
                                 *
                                 * @param {http.Server} httpServer
                                 */
                                constructor(httpServer) {
                                    this.httpServer = httpServer;
                            
                                    this.init();
                                }
                            
                                /**
                                 * Internal method that is called in constructor to initialize
                                 *
                                 * @private
                                 */
                                init() {
                                    this.ws = new WebSocketServer({server: this.httpServer});
                                    this.ws.on('connection', async (webSocket, request, client) => {
                                        if (DEBUG) console.log('New device connected!');
                                        
                                        this.sockets.push( webSocket); // Added to force close ioBroker
                                        webSocket.on('message', async (message) => {
                                            message = JSON.parse(message.toString());
                            
                                            this._clients[message.src] = webSocket;
                                            webSocket.clientId = message.src;
                            
                                            let [model, deviceId] = message.src.split("-");
                            
                                            if (message.method) {
                                                let method = message.method;
                                                let params = message.params;
                                                // console.log('New message', message, model, deviceId, method, params);
                            
                                                if (method === "NotifyFullStatus") {
                                                    this._statuses[message.src] = params;
                                                    let allConfig = await this.call(message.src, "Shelly.getconfig");
                                                    // console.error("allConfig", allConfig);
                                                    this._config[message.src] = allConfig;
                                                }
                                                else if (method === "NotifyStatus") {
                                                    this._statuses[message.src] = mergeDeep(this._statuses[message.src] || {}, params);
                                                }
                                                else if (method === "NotifyEvent") {
                                                    for (let event of params.events) {
                                                        if (event.event === "config_changed") {
                                                            let config = await this.call(message.src, event.component + ".getconfig");
                                                            // console.error("updated config:", config);
                                                            this._config[message.src][event.component] = config;
                                                        }
                                                    }
                                                }
                            
                            
                                                // proceed to call handlers
                                                if (this.handlers[method]) {
                                                    this._callHandler(method, message.src, params, webSocket);
                                                }
                                            }
                                            else if (message.result) {
                                                if (message.id && this._requests[message.id]) {
                                                    this._requests[message.id](message.result);
                                                }
                                                // TODO: log error/warning?
                                            }
                                        });
                            
                                        await this.call(webSocket, "shelly.getdeviceinfo");
                            
                                        // console.error("new connection", request.socket.remoteAddress);
                                    });
                                    this.ws.on('close', (webSocket) => {
                                        this._callHandler("OWS::Disconnected", webSocket.clientId, undefined, webSocket);
                                        cld("Disconnected");
                                        delete this._clients[webSocket.clientId];
                                    })
                                }
                            
                                /**
                                 * Internal.
                                 *
                                 * @param {string} method
                                 * @param {string} id
                                 * @param {Object} params
                                 * @param {WebSocket} webSocket
                                 * @private
                                 */
                                _callHandler(method, id, params, webSocket) {
                                    if (this.handlers[method]) {
                                        let [model, deviceId] = id.split("-");
                            
                                        for (let k of Object.keys(this.handlers[method])) {
                                            let cb = this.handlers[method][k];
                            
                                            try {
                                                cb.call(this, id, params, webSocket, model, deviceId);
                                            } catch (ex) {
                                                console.error("Handler", method, 'thrown error:', ex);
                                            }
                                        }
                                    }
                                }
                            
                                /**
                                 * Add new handler
                                 *
                                 * @param {string} method
                                 * @param {Function} cb
                                 * @returns {number} ID of the handler, that can be used later with `removeHandler`
                                 */
                                addHandler(method, cb) {
                                    let id = this._idx++;
                                    if (!this.handlers[method]) {
                                        this.handlers[method] = {};
                                    }
                                    this.handlers[method][id] = cb;
                                    return id;
                                }
                            
                                /**
                                 * Remove handler
                                 *
                                 * @param {string} method
                                 * @param {number} id
                                 */
                                removeHandler(method, id) {
                                    delete this.handlers[method][id];
                                }
                            
                                /**
                                 * Call a RPC on a target device id OR webSocket directly
                                 *
                                 * @param {string|WebSocket} deviceIdOrWebSocket
                                 * @param {string} method
                                 * @param {Object} params
                                 * @returns {Promise<never>|Promise<unknown>}
                                 */
                                call(deviceIdOrWebSocket, method, params) {
                                    let webSocket = deviceIdOrWebSocket instanceof WebSocket ?
                                        deviceIdOrWebSocket : this._clients[deviceIdOrWebSocket];
                            
                                    if (!webSocket) {
                                        // console.error(this._clients);
                                        return Promise.reject(404);
                                    }
                            
                                    return new Promise((res, rej) => {
                                        let id = this._idx++;
                                        this._requests[id] = (response) => {
                                            res(response);
                                        };
                                        // todo: timeout
                            
                                        let req = {"jsonrpc":"2.0", "id": id, "src":"wsserver", "method": method};
                                        if (params) {
                                            req['params'] = params;
                                        }
                                        // console.debug("Calling:", deviceId, req);
                                        webSocket.send(JSON.stringify(req));
                                    });
                                }
                            
                                /**
                                 * Return current (in-memory cached) device status
                                 *
                                 * @param {string} clientId
                                 * @returns {*|{}}
                                 */
                                getState(clientId) {
                                   return this._statuses[clientId] || {};
                                }
                            
                                /**
                                 * Return current (in-memory cached) device config
                                 *
                                 * @param {string} clientId
                                 * @returns {*|{}}
                                 */
                                getConfig(clientId) {
                                    return this._config[clientId] || {};
                                }
                            
                                /**
                                 * Update config (also updates local cache)
                                 *
                                 * @param {string} clientId
                                 * @param {string} component
                                 * @param {Object} config
                                 * @returns {Promise<*>}
                                 */
                                async setConfig(clientId, component, config) {
                                    // Since response is returned before the notification, we need to sync our local config first, so that immediate
                                    // access to config would return the updated data.
                                    //
                                    // If you don't want that to happen, feel free to .call Component.SetConfig directly.
                            
                                    component = component.toLowerCase();
                            
                                    await this.call(clientId, component + ".setconfig", {'config': config});
                            
                                    this._config[clientId][component] = mergeDeep(this._config[clientId][component] || {}, config);
                                    return this._config[clientId][component];
                                }
                            
                                /**
                                 * Return ids of all clients currently connected.
                                 *
                                 * @returns {string[]}
                                 */
                                getClients() {
                                    return Object.keys(this._clients);
                                }
                            }
                            
                            
                            /**
                             * #########################################################################################################################
                             * ############ Merge from Server and Script  from page: https://github.com/ALLTERCO/shelly-outbound-websockets ############
                             * #########################################################################################################################
                             */
                            
                            
                            const http = require('http')
                            
                            console.log('WS server starting at port ' + port);
                            
                            const httpServer = http.createServer()
                            
                            let shellyOws = new ShellyOWS(httpServer);
                            
                            
                            let idHandler = shellyOws.addHandler("NotifyEvent", async (clientId, params) => {
                                if (DEBUG) console.log( clientId + " | " + JSON.stringify( params) );
                            
                                if ( params.events[0].event !== "ShellyScanresult") return 
                            
                                let val = params.events[0].data.rssi;
                            
                                let StateDef = {
                                    id: `ShellyWebserver.ScanEvent.${params.events[0].data.addr}.${clientId}`,
                                    initial: val,
                                    forceCreation: false,
                                    common: { role: "state", read: true, write: false, name: "RSSI", type: "number" },
                                    native: {}
                                }
                            
                            
                                if ( existsState( `javascript.${instance}.${StateDef.id}`) ){
                                    setState( StateDef.id, val);
                                } else {
                                    createState(StateDef.id, StateDef.initial, StateDef.forceCreation, StateDef.common, StateDef.native);
                                }
                            
                            });
                            
                            httpServer.listen( port);
                            
                            
                            
                            
                            
                            function closeWS() {
                                console.log("Close http server connection.");
                                shellyOws.removeHandler( "NotifyEvent", idHandler);
                                shellyOws.sockets.forEach( socket => {
                                    socket.close()
                                });
                                httpServer.close();
                            }
                            onStop(closeWS, 1000);
                            
                            

                            Ich muss ernüchternd feststellen, dass mein MiBand 6 gerade gar nicht mehr vom Shelly erkannt wird. Zuletzt wurde es erkannt, wenn auch nur alle 10 - 15 Sekunden. Da hatte ich aber noch versucht meine Pixel Watch über iBeacon zu erkennen (erfolglos). Nun hatte ich den Test mit dem MiBand machen wollen, wird nicht angezeigt. Aber grundsätzlich funktioniert das Skript.

                            Die Struktur der States schaut wie folgt aus:

                            javascript.INSTANZ*.ShellyWebserver.ScanEvent.MAC*.SHELLYDEVICE*

                            INSTANZ: Entspricht Instanz des Skripts in ioBroker
                            MAC: Gefundene Mac Adresse während des Scans
                            SHELLYDEVICE: Jeder Shelly schreibt seinen RSSI Wert unter seinem eigenen State

                            1189cb1f-3c71-4e28-a8e9-2176b0e6d025-image.png

                            Ich werde, nach jetzigem Stand, das Scannen mit der aktuellen original Shelly Firmware nicht mehr weiter verfolgen. Habe das Gefühl dass das Thema bei Shelly nicht ausgereift ist. Vor allem wird meine MiBand nicht konsequent gefunden. Was ich absolut nicht verstehen kann. Über den Android Scanner meines Handys oder über Espresense funktioniert es einwandfrei.

                            Ich werde mich wahrscheinlich in Tasmota nochmals versuchen. Zuletzt hatte die Schaltererkennung evtl. nicht funktioniert, weil mein Shelly einer aktuelleren Hardware entspricht.

                            U 1 Antwort Letzte Antwort
                            1
                            • G GiuseppeS

                              @utze86

                              Habe nun das Skript überarbeitet, sodass die RSSI Werte in States geschrieben werden. Anbei die aktuellen Stände:

                              Skript Shelly:

                              function scanCB(ev, res) {
                                  if (ev === BLE.Scanner.SCAN_RESULT) {
                                      let mac = res.addr;
                                      let rssi = res.rssi;
                                      let macType = res.addr_type;
                                      
                                      //print( JSON.stringify( res));
                                      
                                      if ( macType < 3){
                                        let JsonMsg = { "addr": mac, "rssi": rssi };
                                        //print(JSON.stringify( JsonMsg) );
                                        Shelly.emitEvent( "ShellyScanresult", JsonMsg);
                                      }
                                  }
                              }
                              
                              BLE.Scanner.Start({ duration_ms: -1}, scanCB);
                              

                              Skript iobroker:

                              const {WebSocketServer, WebSocket} = require('ws');
                              
                              const port = 8085;
                              
                              const DEBUG = false;
                              
                              /**
                               * Simple object check.
                               * @param item
                               * @returns {boolean}
                               */
                              function isObject(item) {
                                  return (item && typeof item === 'object' && !Array.isArray(item));
                              }
                              
                              /**
                               * Deep merge two objects.
                               * @param target
                               * @param ...sources
                               */
                              function mergeDeep(target, ...sources) {
                                  if (!sources.length) return target;
                                  const source = sources.shift();
                              
                                  if (isObject(target) && isObject(source)) {
                                      for (const key in source) {
                                          if (isObject(source[key])) {
                                              if (!target[key]) Object.assign(target, { [key]: {} });
                                              mergeDeep(target[key], source[key]);
                                          } else {
                                              Object.assign(target, { [key]: source[key] });
                                          }
                                      }
                                  }
                              
                                  return mergeDeep(target, ...sources);
                              }
                              
                              /**
                               * Shelly Outbound WebSocket
                               */
                              class ShellyOWS {
                                  handlers = {};
                                  _idx = 0;
                                  httpServer = null;
                                  _clients = {};
                                  _statuses = {};
                                  _config = {};
                                  _requests = {};
                                  ws = null;
                                  sockets = [];
                              
                                  /**
                                   * Init ShellyOWS with an existing httpServer
                                   *
                                   * @param {http.Server} httpServer
                                   */
                                  constructor(httpServer) {
                                      this.httpServer = httpServer;
                              
                                      this.init();
                                  }
                              
                                  /**
                                   * Internal method that is called in constructor to initialize
                                   *
                                   * @private
                                   */
                                  init() {
                                      this.ws = new WebSocketServer({server: this.httpServer});
                                      this.ws.on('connection', async (webSocket, request, client) => {
                                          if (DEBUG) console.log('New device connected!');
                                          
                                          this.sockets.push( webSocket); // Added to force close ioBroker
                                          webSocket.on('message', async (message) => {
                                              message = JSON.parse(message.toString());
                              
                                              this._clients[message.src] = webSocket;
                                              webSocket.clientId = message.src;
                              
                                              let [model, deviceId] = message.src.split("-");
                              
                                              if (message.method) {
                                                  let method = message.method;
                                                  let params = message.params;
                                                  // console.log('New message', message, model, deviceId, method, params);
                              
                                                  if (method === "NotifyFullStatus") {
                                                      this._statuses[message.src] = params;
                                                      let allConfig = await this.call(message.src, "Shelly.getconfig");
                                                      // console.error("allConfig", allConfig);
                                                      this._config[message.src] = allConfig;
                                                  }
                                                  else if (method === "NotifyStatus") {
                                                      this._statuses[message.src] = mergeDeep(this._statuses[message.src] || {}, params);
                                                  }
                                                  else if (method === "NotifyEvent") {
                                                      for (let event of params.events) {
                                                          if (event.event === "config_changed") {
                                                              let config = await this.call(message.src, event.component + ".getconfig");
                                                              // console.error("updated config:", config);
                                                              this._config[message.src][event.component] = config;
                                                          }
                                                      }
                                                  }
                              
                              
                                                  // proceed to call handlers
                                                  if (this.handlers[method]) {
                                                      this._callHandler(method, message.src, params, webSocket);
                                                  }
                                              }
                                              else if (message.result) {
                                                  if (message.id && this._requests[message.id]) {
                                                      this._requests[message.id](message.result);
                                                  }
                                                  // TODO: log error/warning?
                                              }
                                          });
                              
                                          await this.call(webSocket, "shelly.getdeviceinfo");
                              
                                          // console.error("new connection", request.socket.remoteAddress);
                                      });
                                      this.ws.on('close', (webSocket) => {
                                          this._callHandler("OWS::Disconnected", webSocket.clientId, undefined, webSocket);
                                          cld("Disconnected");
                                          delete this._clients[webSocket.clientId];
                                      })
                                  }
                              
                                  /**
                                   * Internal.
                                   *
                                   * @param {string} method
                                   * @param {string} id
                                   * @param {Object} params
                                   * @param {WebSocket} webSocket
                                   * @private
                                   */
                                  _callHandler(method, id, params, webSocket) {
                                      if (this.handlers[method]) {
                                          let [model, deviceId] = id.split("-");
                              
                                          for (let k of Object.keys(this.handlers[method])) {
                                              let cb = this.handlers[method][k];
                              
                                              try {
                                                  cb.call(this, id, params, webSocket, model, deviceId);
                                              } catch (ex) {
                                                  console.error("Handler", method, 'thrown error:', ex);
                                              }
                                          }
                                      }
                                  }
                              
                                  /**
                                   * Add new handler
                                   *
                                   * @param {string} method
                                   * @param {Function} cb
                                   * @returns {number} ID of the handler, that can be used later with `removeHandler`
                                   */
                                  addHandler(method, cb) {
                                      let id = this._idx++;
                                      if (!this.handlers[method]) {
                                          this.handlers[method] = {};
                                      }
                                      this.handlers[method][id] = cb;
                                      return id;
                                  }
                              
                                  /**
                                   * Remove handler
                                   *
                                   * @param {string} method
                                   * @param {number} id
                                   */
                                  removeHandler(method, id) {
                                      delete this.handlers[method][id];
                                  }
                              
                                  /**
                                   * Call a RPC on a target device id OR webSocket directly
                                   *
                                   * @param {string|WebSocket} deviceIdOrWebSocket
                                   * @param {string} method
                                   * @param {Object} params
                                   * @returns {Promise<never>|Promise<unknown>}
                                   */
                                  call(deviceIdOrWebSocket, method, params) {
                                      let webSocket = deviceIdOrWebSocket instanceof WebSocket ?
                                          deviceIdOrWebSocket : this._clients[deviceIdOrWebSocket];
                              
                                      if (!webSocket) {
                                          // console.error(this._clients);
                                          return Promise.reject(404);
                                      }
                              
                                      return new Promise((res, rej) => {
                                          let id = this._idx++;
                                          this._requests[id] = (response) => {
                                              res(response);
                                          };
                                          // todo: timeout
                              
                                          let req = {"jsonrpc":"2.0", "id": id, "src":"wsserver", "method": method};
                                          if (params) {
                                              req['params'] = params;
                                          }
                                          // console.debug("Calling:", deviceId, req);
                                          webSocket.send(JSON.stringify(req));
                                      });
                                  }
                              
                                  /**
                                   * Return current (in-memory cached) device status
                                   *
                                   * @param {string} clientId
                                   * @returns {*|{}}
                                   */
                                  getState(clientId) {
                                     return this._statuses[clientId] || {};
                                  }
                              
                                  /**
                                   * Return current (in-memory cached) device config
                                   *
                                   * @param {string} clientId
                                   * @returns {*|{}}
                                   */
                                  getConfig(clientId) {
                                      return this._config[clientId] || {};
                                  }
                              
                                  /**
                                   * Update config (also updates local cache)
                                   *
                                   * @param {string} clientId
                                   * @param {string} component
                                   * @param {Object} config
                                   * @returns {Promise<*>}
                                   */
                                  async setConfig(clientId, component, config) {
                                      // Since response is returned before the notification, we need to sync our local config first, so that immediate
                                      // access to config would return the updated data.
                                      //
                                      // If you don't want that to happen, feel free to .call Component.SetConfig directly.
                              
                                      component = component.toLowerCase();
                              
                                      await this.call(clientId, component + ".setconfig", {'config': config});
                              
                                      this._config[clientId][component] = mergeDeep(this._config[clientId][component] || {}, config);
                                      return this._config[clientId][component];
                                  }
                              
                                  /**
                                   * Return ids of all clients currently connected.
                                   *
                                   * @returns {string[]}
                                   */
                                  getClients() {
                                      return Object.keys(this._clients);
                                  }
                              }
                              
                              
                              /**
                               * #########################################################################################################################
                               * ############ Merge from Server and Script  from page: https://github.com/ALLTERCO/shelly-outbound-websockets ############
                               * #########################################################################################################################
                               */
                              
                              
                              const http = require('http')
                              
                              console.log('WS server starting at port ' + port);
                              
                              const httpServer = http.createServer()
                              
                              let shellyOws = new ShellyOWS(httpServer);
                              
                              
                              let idHandler = shellyOws.addHandler("NotifyEvent", async (clientId, params) => {
                                  if (DEBUG) console.log( clientId + " | " + JSON.stringify( params) );
                              
                                  if ( params.events[0].event !== "ShellyScanresult") return 
                              
                                  let val = params.events[0].data.rssi;
                              
                                  let StateDef = {
                                      id: `ShellyWebserver.ScanEvent.${params.events[0].data.addr}.${clientId}`,
                                      initial: val,
                                      forceCreation: false,
                                      common: { role: "state", read: true, write: false, name: "RSSI", type: "number" },
                                      native: {}
                                  }
                              
                              
                                  if ( existsState( `javascript.${instance}.${StateDef.id}`) ){
                                      setState( StateDef.id, val);
                                  } else {
                                      createState(StateDef.id, StateDef.initial, StateDef.forceCreation, StateDef.common, StateDef.native);
                                  }
                              
                              });
                              
                              httpServer.listen( port);
                              
                              
                              
                              
                              
                              function closeWS() {
                                  console.log("Close http server connection.");
                                  shellyOws.removeHandler( "NotifyEvent", idHandler);
                                  shellyOws.sockets.forEach( socket => {
                                      socket.close()
                                  });
                                  httpServer.close();
                              }
                              onStop(closeWS, 1000);
                              
                              

                              Ich muss ernüchternd feststellen, dass mein MiBand 6 gerade gar nicht mehr vom Shelly erkannt wird. Zuletzt wurde es erkannt, wenn auch nur alle 10 - 15 Sekunden. Da hatte ich aber noch versucht meine Pixel Watch über iBeacon zu erkennen (erfolglos). Nun hatte ich den Test mit dem MiBand machen wollen, wird nicht angezeigt. Aber grundsätzlich funktioniert das Skript.

                              Die Struktur der States schaut wie folgt aus:

                              javascript.INSTANZ*.ShellyWebserver.ScanEvent.MAC*.SHELLYDEVICE*

                              INSTANZ: Entspricht Instanz des Skripts in ioBroker
                              MAC: Gefundene Mac Adresse während des Scans
                              SHELLYDEVICE: Jeder Shelly schreibt seinen RSSI Wert unter seinem eigenen State

                              1189cb1f-3c71-4e28-a8e9-2176b0e6d025-image.png

                              Ich werde, nach jetzigem Stand, das Scannen mit der aktuellen original Shelly Firmware nicht mehr weiter verfolgen. Habe das Gefühl dass das Thema bei Shelly nicht ausgereift ist. Vor allem wird meine MiBand nicht konsequent gefunden. Was ich absolut nicht verstehen kann. Über den Android Scanner meines Handys oder über Espresense funktioniert es einwandfrei.

                              Ich werde mich wahrscheinlich in Tasmota nochmals versuchen. Zuletzt hatte die Schaltererkennung evtl. nicht funktioniert, weil mein Shelly einer aktuelleren Hardware entspricht.

                              U Offline
                              U Offline
                              Utze86
                              schrieb am zuletzt editiert von
                              #176

                              @giuseppes Danke für die Skripte. Leider kann ich auch keine positive Rückmeldung geben. Mit der Shelly Firmware erhalte ich im Durchschnitt nur alle 7-8 Sekunden ein Signal von meinem Mi Band. Das Ergebnis ist also wesentlich schlechter als die Auswertung über Tasmota. Ich werde im nächsten Schritt ein paar Shellys mit Tasmota flashen und mich um die Umsetzung der Anwesenheitserkennung kümmern.

                              G 1 Antwort Letzte Antwort
                              1
                              • U Utze86

                                @giuseppes Danke für die Skripte. Leider kann ich auch keine positive Rückmeldung geben. Mit der Shelly Firmware erhalte ich im Durchschnitt nur alle 7-8 Sekunden ein Signal von meinem Mi Band. Das Ergebnis ist also wesentlich schlechter als die Auswertung über Tasmota. Ich werde im nächsten Schritt ein paar Shellys mit Tasmota flashen und mich um die Umsetzung der Anwesenheitserkennung kümmern.

                                G Offline
                                G Offline
                                GiuseppeS
                                schrieb am zuletzt editiert von
                                #177

                                @utze86
                                Tasmota wäre aktuell auch meine erste Wahl. Werde im Testaufbau aber noch prüfen müssen, wieso die Schaltereingänge im detached Modus teilweise so spät erkannt werden. Benötige ich für zwei Fälle.

                                U 1 Antwort Letzte Antwort
                                0
                                • stolly82S Offline
                                  stolly82S Offline
                                  stolly82
                                  schrieb am zuletzt editiert von stolly82
                                  #178

                                  @giuseppes

                                  Wie bekommen ich den Websocket im JavaScript Adapter zum laufen?

                                  20:55:37.971	info	javascript.1 (30342) Start javascript script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly
                                  20:55:38.124	info	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: WS server starting at port 8085
                                  20:55:38.132	info	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: registered 0 subscriptions and 0 schedules
                                  20:55:38.176	error	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: TypeError: WebSocketServer is not a constructor
                                  20:55:38.179	error	javascript.1 (30342) at ShellyOWS.init (script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:70:19)
                                  20:55:38.181	error	javascript.1 (30342) at new ShellyOWS (script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:61:14)
                                  20:55:38.183	error	javascript.1 (30342) at script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:282:17
                                  20:55:38.184	error	javascript.1 (30342) at script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:324:3
                                  

                                  e20d8ed0-01bb-4506-8b9d-4943b4bafe00-image.png
                                  Zusätzliche NPM Module ws oder websocket läuft leider nicht :(

                                  G 2 Antworten Letzte Antwort
                                  0
                                  • stolly82S stolly82

                                    @giuseppes

                                    Wie bekommen ich den Websocket im JavaScript Adapter zum laufen?

                                    20:55:37.971	info	javascript.1 (30342) Start javascript script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly
                                    20:55:38.124	info	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: WS server starting at port 8085
                                    20:55:38.132	info	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: registered 0 subscriptions and 0 schedules
                                    20:55:38.176	error	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: TypeError: WebSocketServer is not a constructor
                                    20:55:38.179	error	javascript.1 (30342) at ShellyOWS.init (script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:70:19)
                                    20:55:38.181	error	javascript.1 (30342) at new ShellyOWS (script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:61:14)
                                    20:55:38.183	error	javascript.1 (30342) at script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:282:17
                                    20:55:38.184	error	javascript.1 (30342) at script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:324:3
                                    

                                    e20d8ed0-01bb-4506-8b9d-4943b4bafe00-image.png
                                    Zusätzliche NPM Module ws oder websocket läuft leider nicht :(

                                    G Offline
                                    G Offline
                                    GiuseppeS
                                    schrieb am zuletzt editiert von
                                    #179

                                    @stolly82
                                    Woher weißt du, dass der Server nicht richtig läuft? Ich sehe keine Fehlermeldungen. Port 8085 sollte frei sein, dieser wird vom Server verwendet.

                                    Hast du den Shelly auch korrekt auf den Server eingerichtet?

                                    1 Antwort Letzte Antwort
                                    0
                                    • stolly82S stolly82

                                      @giuseppes

                                      Wie bekommen ich den Websocket im JavaScript Adapter zum laufen?

                                      20:55:37.971	info	javascript.1 (30342) Start javascript script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly
                                      20:55:38.124	info	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: WS server starting at port 8085
                                      20:55:38.132	info	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: registered 0 subscriptions and 0 schedules
                                      20:55:38.176	error	javascript.1 (30342) script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly: TypeError: WebSocketServer is not a constructor
                                      20:55:38.179	error	javascript.1 (30342) at ShellyOWS.init (script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:70:19)
                                      20:55:38.181	error	javascript.1 (30342) at new ShellyOWS (script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:61:14)
                                      20:55:38.183	error	javascript.1 (30342) at script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:282:17
                                      20:55:38.184	error	javascript.1 (30342) at script.js.Rules.Allgemein.Lokalisierung.Indoor_-_Shelly:324:3
                                      

                                      e20d8ed0-01bb-4506-8b9d-4943b4bafe00-image.png
                                      Zusätzliche NPM Module ws oder websocket läuft leider nicht :(

                                      G Offline
                                      G Offline
                                      GiuseppeS
                                      schrieb am zuletzt editiert von
                                      #180

                                      @stolly82
                                      Nur ws ist als Modul notwendig

                                      1 Antwort Letzte Antwort
                                      0
                                      • G GiuseppeS

                                        @utze86
                                        Tasmota wäre aktuell auch meine erste Wahl. Werde im Testaufbau aber noch prüfen müssen, wieso die Schaltereingänge im detached Modus teilweise so spät erkannt werden. Benötige ich für zwei Fälle.

                                        U Offline
                                        U Offline
                                        Utze86
                                        schrieb am zuletzt editiert von Utze86
                                        #181

                                        @giuseppes Nochmal eine kleine Rückmeldung zum Shelly. Ich habe das Skript nochmal mit der aktuellen stable Firmware von Shelly getestet. Diesen letzten Test wollte ich dann noch nochmal durchführen als ich gesehen habe, dass es ein Update gibt. Hier habe ich allerdings ein ähnliches Problem wie du: Das Mi Band wird komischer Weise gar nicht mehr erkannt. Keine Ahnung ob es am BLE in Kombi mit dem Band und dem Shelly liegt. Andere Geräte werden teils mehrfach die Sekunde erkannt. Der Trend geht also weiter zu Tasmota.

                                        Hast du eigentlich inzwischen eine Möglichkeit gefunden die Shelly Firmware wieder zurück auf den Shelly zu bekommen wenn dort einmal Tasmota installiert wurde? Bisher konnte ich online keine original Firmware finden. Die Firmware von einem anderen Shelly runter ziehen fällt aktuell leider Flach da mein USB/Serial Adapter scheinbar den Geist aufgegeben hat. Aber ich habe gesehen, dass die Shellys sich inzwischen OTA mit verschiedenen Firmwaren flashen lassen. Was natürlich mega praktisch ist, vorallem wenn die Dinger bereits verbaut sind. Also falls du eine originale Firmware hast wäre es cool wenn du sie mir zur Verfügung stellen könntest.

                                        EDIT: OTA geht natürlich nicht von Original FW zu Tasmota :-(

                                        G 1 Antwort Letzte Antwort
                                        0
                                        • U Utze86

                                          @giuseppes Nochmal eine kleine Rückmeldung zum Shelly. Ich habe das Skript nochmal mit der aktuellen stable Firmware von Shelly getestet. Diesen letzten Test wollte ich dann noch nochmal durchführen als ich gesehen habe, dass es ein Update gibt. Hier habe ich allerdings ein ähnliches Problem wie du: Das Mi Band wird komischer Weise gar nicht mehr erkannt. Keine Ahnung ob es am BLE in Kombi mit dem Band und dem Shelly liegt. Andere Geräte werden teils mehrfach die Sekunde erkannt. Der Trend geht also weiter zu Tasmota.

                                          Hast du eigentlich inzwischen eine Möglichkeit gefunden die Shelly Firmware wieder zurück auf den Shelly zu bekommen wenn dort einmal Tasmota installiert wurde? Bisher konnte ich online keine original Firmware finden. Die Firmware von einem anderen Shelly runter ziehen fällt aktuell leider Flach da mein USB/Serial Adapter scheinbar den Geist aufgegeben hat. Aber ich habe gesehen, dass die Shellys sich inzwischen OTA mit verschiedenen Firmwaren flashen lassen. Was natürlich mega praktisch ist, vorallem wenn die Dinger bereits verbaut sind. Also falls du eine originale Firmware hast wäre es cool wenn du sie mir zur Verfügung stellen könntest.

                                          EDIT: OTA geht natürlich nicht von Original FW zu Tasmota :-(

                                          G Offline
                                          G Offline
                                          GiuseppeS
                                          schrieb am zuletzt editiert von
                                          #182

                                          @utze86
                                          Habe selbst noch keine original Firmware finden können, daher ist ein Flashen zurück auf original auch für mich nicht möglich. Über die Möglichkeit, die Firmware von einem anderem Gerät zu ziehen, hatte ich noch gar nicht nachgedacht.
                                          Ich habe übrigens meine Pixel Watch verkauft und mir die Amazfit GTS 4 Mini geholt. Diese sendet, wie das Mi Band, konstant Advertisements. Aber auch diese wird vom Shelly nicht gefunden, egal ob original Firmware oder Tasmota. Daher habe ich nun meine zwei Test-Shelly auf Facebook zum Verkauf angeboten. Ich überlege nun original esp32 mit espresense zu verwenden. Ich hatte versucht espresense für die Shelly zu kompilieren, funktionierte anscheinend, aber irgendwas führt dann zu einem kritischen Fehler und der Shelly bootet. Hatte schon einen Schaltereingang zu Testzwecken im espresense Code integriert... überlege nun worauf ich mich konzentrieren soll. Zeit ist ein begrenztes Gut.
                                          Werde mich mal schlau machen, wie ich Firmware von einem Shelly downloaden kann und melde mich wenn erfolgreich.

                                          U 2 Antworten Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          744

                                          Online

                                          32.4k

                                          Benutzer

                                          81.5k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe