Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. uweabc

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    U
    • Profile
    • Following 1
    • Followers 0
    • Topics 1
    • Posts 26
    • Best 8
    • Groups 1

    uweabc

    @uweabc

    Starter

    11
    Reputation
    50
    Profile views
    26
    Posts
    0
    Followers
    1
    Following
    Joined Last Online

    uweabc Follow
    Starter

    Best posts made by uweabc

    • RE: IOBroker mit Smartvisu

      Bei basic.flip true,false einfach weglassen.
      Ob man nun true, false oder 1,0 oder 'true','false' in den Widgets (z.B. basic.checkbox) verwendet sollte kein Unterschied machen, da die Typenkonvertierung in smartVISU 3.3.0 dies wieder korrigiert. Also wenn ioBroker ein boolean liefert so schreibt smartVISU 3.3.0 auch ein boolean wieder zurück.

      Ich habe dazu eine Objekt definiert:

      {
        "common": {
          "name": "boolean Test",
          "type": "boolean",
          "def": false,
          "role": "state"
        },
        "native": {},
        "type": "state",
        "_id": "0_userdata.0.boolean_value",
        "acl": {
          "object": 1636,
          "state": 1636,
          "owner": "system.user.admin",
          "ownerGroup": "system.group.administrator"
        },
        "from": "system.adapter.admin.0",
        "user": "system.user.admin",
        "ts": 1671443159460
      }
      

      In einer smartVISU Testseite die zu testenden Widgets definiert:

        <div class="block">
          <div class="set-2" data-role="collapsible-set" data-theme="c" data-content-theme="a" data-mini="true">
            <div data-role="collapsible" data-collapsed="false">
              <h3>boolean value test</h3>
                basic.checkbox {{ basic.checkbox('', '0_userdata.0.boolean_value', 'boolean', true, false) }}<br>
      	  basic.stateswitch {{ basic.stateswitch('', '0_userdata.0.boolean_value', 'icon', [true,false], ['jquery_plus.svg', 'jquery_minus.svg']) }}<br>
      	  basic.flip {{ basic.flip('flip', '0_userdata.0.boolean_value') }}<br>
      	  {{ basic.print('', '0_userdata.0.boolean_value', '%s' , 'VAR==1?"true":"false"') }}<br>
            </div>
          </div>
        </div>
      

      Und dies getestet:
      ioBroker_smartVisu_boolean.gif

      Dies sieht man in Log (ioBroker):

      socketio.0 2022-12-21 19:19:49.419	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":true,"ack":false,"ts":1671646789416,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646789416}
      socketio.0 2022-12-21 19:19:47.064	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":false,"ack":false,"ts":1671646787061,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646787061}
      socketio.0 2022-12-21 19:19:44.001	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":true,"ack":false,"ts":1671646783998,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646783998}
      socketio.0 2022-12-21 19:19:41.201	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":false,"ack":false,"ts":1671646781198,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646781198}```
      posted in ioBroker Allgemein
      U
      uweabc
    • [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      ALLE VERKAUFT

      Es wurden alle verkauft.

      Hersteller "Ich"
      Model "Long Range CC2538+CC2592 ZigBee 3.0.2 USB Stick V5"
      Anzahl keine
      *Preis pro Stück 39 €
      Versand "Ja, Warensendung ohne Aufpreis (nach DE) / Abholung / Kontakt per PN"
      ----------------- ---
      Beschreibung "Verbessertes RF-Design für erhöhte Reichweite, Leistungsstarker CC2538+CC2592 ZigBee 3.0.2 USB Stick, mit 3,5 dBi Antenne"

      Direkt einsatzfähiger Coordinator (Gateway) für unterschiedlichen SmartHome Server wie Domoticz, Home-Assistant, ioBroker und so weiter... (Firmware ist aufgespielt)
      Das besondere an diesem Stick, es können bis zu 200 Geräte an einem Stick angemeldet werden, das ist um ein Vielfaches mehr als beim CC2531. Neben seiner verbesserten Sendeleistung bietet der CC2538+CC2592 auch eine stärkere Rechenleistung.
      Alle ZigBee Sticks wurden auf Funktion getestet (mit ioBocker & "Ikea Tradfri ON/OFF Switch" in 25 Meter Entfernung geschlossener Raum).
      A_P1230001.JPG A2_P1230017.JPG A3_P1230006.JPG A4_P1230007.JPG A5_P1230021.JPG

      • bis zu 200 Geräte können an diesem Stick angemeldet werden (andere Sticks können ca. 20-50)
      • hohe Reichweite durch Signal­verstärker
      • Signalreichweite 500 m im Freifeld
      • Betriebssysteme Microsoft Windows 7 / 8.1 / 10, Ubuntu, Raspbian, Docker
      • verbessertes RF-Design für erhöhte Reichweite, im Funklabor verifiziert (optimierte Leiterbahnführung gegenüber dem "MODKAMRU Zigbee V3 USB stick")
      • funktioniert mit bekannten Home Automation Systemen, Kompatibel mit Zigbee2MQTT, ioBroker, Home Assistant, Domoticz, FHEM, openHAB usw.
      • unter Zigbee2MQTT werden derzeit > 1050 Geräte von 175 verschiedenen Anbietern unterstützt (www.zigbee2mqtt.io/information/supported_devices.html)
      • unter ioBroker werden derzeit > 300 (dokumentiert) Geräte von > 70 verschiedenen Anbietern unterstützt (github.com/ioBroker/ioBroker.zigbee/wiki/Supported-devices)
      • Firmware basiert auf Z-Stack 3.0.2 und MODKAMRU (geladen github.com/egony/MODKAM-STICK-V3/blob/master/firmware/cc2538/Riverieline_2020-02/MODKAMRU_V3_USB_with_SBL.hex)
      • 4 Status-LED's, abschaltbar über Software (z.B. im ioBroker ZigBeeAdapter)
      • Resettaste
      • serieller Bootloader über Microtaster aktivierbar (nur RX & TX und GND wird für Firmware Update benötigt, kein extra JTAG Debugger)
      • Firmware Update auch ohne JLink Debugger möglich
      • JTAG Debugger / Flash Anschuss (JLink)
      • optimierte Schaltung gegenüber dem MODKAMRU-PCB
      • kann in einem USB-Stick-Gehäuse verbaut werden (Hammond Electronics 1551USB3BK USB-Gehäuse 65 x 30 x 15.5)

      Lieferumfang:

      • CC2538 + CC2592 ZigBee Stick mit Z-Stack 3.0.2
      • funktionstüchtig und auf Reichweite 25m (Indoor, Wohngebäude) getestet
      • 3,5 dBi Antenne
      • mit schützendem transparenten Schrumpfschlauch
      posted in Marktplatz
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      @arteck sagte in Long Range CC2538 + CC2592 ZigBee 3.0.2 USB Stick V5:

      die Firmware für das Modul hat es so eingstellt
      1604910424961-bcaf3997-c2c1-4934-a74c-9b4f06d28db8-grafik.png

      Ja die Tabelle stimmt: an ZC 100 und mit ZR 200 unter ZigBee 3.0, bei mir sind es aktuell 87 ZEDs unter FHEM mit 3 ZR und einem ZC.

      Bei homee ist so bei 23 ZED schluss (4 Dimmer, 19 Hue Leuchten), Osram 50, der CC2531 macht bei mir schon bei 13 ZED schlapp, ConBee bei 22 ZED, alles ohne ZR. Das sind so meine Erfahrungen.

      @arteck sagte in Long Range CC2538 + CC2592 ZigBee 3.0.2 USB Stick V5:

      optimierte Firmware: Verzögerung zwischen Befehlen von standardmäßig 250ms auf 50ms reduziert

      na da bin ich mal gespannt .. wenn Fehler aufkommen wenn Befehle nicht durchgehen.bzw. nicht quittiert werden..
      weiss ich bescheid.

      250ms nach 50ms: Verwechlung: das war eine Einstellung in zigbee2mqtt

      Gruß Uwe

      posted in Marktplatz
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      @Asgothian sagte in Long Range CC2538 + CC2592 ZigBee 3.0.2 USB Stick V5:

      Da auf diesem Stick eine besondere FW geflasht wird, und wir diese in Startup-Logs erkennen müssen: Kannst Du bitte der Firmware eine eindeutige Kennung geben und diese in dem Artikel mit angeben - das macht eine Fehlersuche (Siehe auch den Kommentar von @Arteck) deutlich leichter.

      Ich kenne nur die stabile 20200211 Revision. Sicherlich werde ich keine neue Version erstellen, die von Koenkk ist schon relativ stabil.
      @uweabc sagte in Long Range CC2538 + CC2592 ZigBee 3.0.2 USB Stick V5:

      Firmware basiert auf Z-Stack 3.0.2 und MODKAMRU (geladen github.com/egony/MODKAM-STICK-V3/blob/master/firmware/cc2538/Riverieline_2020-02/MODKAMRU_V3_USB_with_SBL.hex)

      Die letzte Zeile im HEX ist auf :0CFFD400FFFFFFF700000000000020000D geändert damit der TI-Bootloader über die Taste aktiviert werden kann. Einfach mal das CC2538 Datenblatt lesen.

      Gruß Uwe

      posted in Marktplatz
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      @norbert2 sagte in Long Range CC2538 + CC2592 ZigBee 3.0.2 USB Stick V5:

      @uweabc
      Hallo Uwe,
      noch eine Frage: ich benutze dieses Zigbee2MQTT, kann ich da einfach diesen ZigBee-Adapter in iobroker verwenden? (komme aus einem anderen "SmartHome Lager").

      Hi Norbert,
      ja, ich verwende den Zigbee Adapter 1.2.1, der funktioniert bei mir hervorragend.

      posted in Marktplatz
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      @mpl1338
      Für ein Repeater ist der zu oversized, ein normaler Repeater ist da günstiger

      posted in Marktplatz
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      ALLE VERKAUFT

      Es wurden alle verkauft, neue Lieferung der Leiterplatten & Bauteile sind unterwegs, da einige User diese Version haben möchten. Sorry aber das ist nur ein Hobby, kann keine Massen liefern.

      Grüße Uwe

      posted in Marktplatz
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      @crawlspace sagte in [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5:

      @uweabc
      Dieser ZigBee Stick hat echt eine große Reichweite, besser als ConBee II. Da hatte ich immer Verbindungsprobleme mit IKEA Geräten (dieser kleine Taster).
      ABER: beim Update des iobroker ZigBee Adapters auf 1.2.1 hagelte es nur von Fehlermeldungen beim updaten, irgendwas mit node. Woran kann das liegen?

      Fehlermeldung ist etwas mager!?
      ich schaue mal in die GLASKUGEL:
      mal node updaten?

      posted in Marktplatz
      U
      uweabc

    Latest posts made by uweabc

    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @jolly
      Ich habe das gemacht:
      pip uninstall msmart-ng
      dann
      pip install msmart-ng

      oder so:
      https://forum.iobroker.net/topic/33198/test-adapter-midea-dimstal-klimaanlagen-v0-0-x/346

      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @bananajoe
      Bei den neuen msmart-ng 2025.7.0 mit --energy angegeben, z.B. so?
      msmart-ng query --region DE --auto --energy 192.168.1.29
      oder auch mit id token und key anstatt --auto

      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @jolly
      Sollte schon gehen, evtl. altes msmart-ng, mach mal
      msmart-ng -v
      Ausgabe: msmart-ng version: 2025.7.0

      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @bananajoe
      mit der neuen Version von
      msmart-ng -v
      Ausgabe: msmart-ng version: 2025.7.0
      werden auch die Energiewerte im ioBroker gefüllt.
      Hier die neue Version des JavaScripts (vorher die alten midea-Objekte, den ganzen Baum, löschen):

      /*
          Version 06.07.2025 Add option to CLI to request energy information
                             ID & Token & Key for msmart-ng are automatically determined
          
          Steuert eine Midea-Klimaanlage direkt über das Python-Programm 'msmart-ng' (siehe unten Installation 'msmart-ng') lokal im WLAN.
          
          Das Gerät wurde einmalig mit der Android-App in das WLAN integriert. 
          Anschließend wurde der Internetzugang für diese Gerät über die FritzBox deaktiviert, um eine Fremdsteuerung zu unterbinden.
          Keine Cloud erforderlich für dieses JavaScript!
      
          Dieses JavaScript übernimmt folgende Funktionen:  
          - Es liest die aktuellen Werte des Geräts im lokalen Netzwerk ab, siehe dazu Variable 'mideaPortaSplit'.  
            IP in Variable 'mideaPortaSplit' muss entsprechend geändert werden. 
            ID + Token + Key werden über 'msmart-ng query --region DE --auto <ip>' automatisch ermittelt.
          - Es erstellt eigenständig die passenden Objekte in ioBroker (unter javascript.0.midea.*).  
          - Wird ein schreibbares Objekt geändert, so schreibt das JavaScript die Änderung direkt ins Gerät, 
            indem es die Befehle über 'msmart-ng' sendet.
            Gültige Werte für FanSpeed / OperationalMode / SwingMode / SwingAngle / RateSelect / BreezeMode / AuxHeatMode
            siehe Variable 'AirConditioner'.
          - Der Loglevel (javascript.0.media.loglevel) kann während der Laufzeit des Skripts angepasst werden. 
            Mögliche Werte sind 0=aus, 1=minimal, 2=alles.
      
          Idee abgeleitet aus den Beitrag: https://forum.iobroker.net/topic/33198/test-adapter-midea-dimstal-klimaanlagen-v0-0-x/346?lang=de
      
          Installation 'msmart-ng':
          =========================
          Zum Benutzer ioBroker wechseln:
              sudo -u iobroker /usr/bin/bash
          In das Home-Verzeichnis des Benutzers ioBroker wechseln
              cd ~
          Python Environment anlegen (falls noch nicht vorhanden):
              python3 -m venv python-venv
          und in die Umgebung wechseln:
              source python-venv/bin/activate
          Jetzt kann man per pip das Modul installieren
              pip install msmart-ng
          und dann Version anzeigen:
              msmart-ng -v
          Ausgabe:        
              msmart-ng version: 2025.7.0
          Vor der Nutzung muss dann aber immer erst das Envirtonment geladen werden.
          Intelligenter weise wird das in den nachinstallierten Python-Modulen gleich richtig hinterlegt:
              which msmart-ng
          Ausgabe:
              /home/iobroker/python-venv/bin/msmart-ng
          Inhalt:
              cat /home/iobroker/python-venv/bin/msmart-ng
          Die erste Zeile ist
              #!/home/iobroker/python-venv/bin/python3
          Womit die richtige Umgebung genutzt wird.
          In ioBroker Skripten den ganzen Pfad aufrufen:
              /home/iobroker/python-venv/bin/msmart-ng
      */
      
      // id + token + key ermittelbar über 'msmart-ng query --region DE --auto 192.168.178.205'
      const mideaPortaSplit = { 
          ip: '192.168.178.205',
          id: null, // Temporary storage, ID for msmart-ng is automatically determined
          token: null, // Temporary storage, token for msmart-ng is automatically determined
          key: null, // Temporary storage, key for msmart-ng is automatically determined
          controlSettings: [], // Temporary storage for all modifiable objects, used in on({id: mideaPortaSplit.controlSettings, change: 'any'}...
      };
      let controlListener;
      
      const basePath = 'javascript.0.midea'; // Base object path
      var LOGLEVEL = 2; // 0=off, 1=minimal, 2=all
      const msmartLoglevel = basePath + '.loglevel';
      const region = 'DE'; // --region {DE,KR,US}
      const msmart_ng = '/home/iobroker/python-venv/bin/msmart-ng';
      
      // Enums see https://github.com/mill1000/midea-msmart/blob/main/msmart/device/AC/device.py
      // Note: The above link is for reference; it contains enum definitions for the device.
      class AirConditioner {
          static FanSpeed = {
              AUTO: 102,
              MAX: 100,
              HIGH: 80,
              MEDIUM: 60,
              LOW: 40,
              SILENT: 20,
              DEFAULT: 102
          };
      
          static OperationalMode = {
              AUTO: 1,
              COOL: 2,
              DRY: 3,
              HEAT: 4,
              FAN_ONLY: 5,
              SMART_DRY: 6,
              DEFAULT: 5
          };
      
          static SwingMode = {
              OFF: 0,
              VERTICAL: 12,
              HORIZONTAL: 3,
              BOTH: 15,
              DEFAULT: 0
          };
      
          static SwingAngle = {
              OFF: 0,
              POS_1: 1,
              POS_2: 25,
              POS_3: 50,
              POS_4: 75,
              POS_5: 100,
              DEFAULT: 0
          };
      
          static RateSelect = {
              OFF: 100,
              GEAR_50: 50,
              GEAR_75: 75,
              LEVEL_1: 1,
              LEVEL_2: 20,
              LEVEL_3: 40,
              LEVEL_4: 60,
              LEVEL_5: 80,
              DEFAULT: 100
          };
      
          static BreezeMode = {
              OFF: 1,
              BREEZE_AWAY: 2,
              BREEZE_MILD: 3,
              BREEZELESS: 4,
              DEFAULT: 1
          };
      
          static AuxHeatMode = {
              OFF: 0,
              AUX_HEAT: 1,
              AUX_ONLY: 2,
              DEFAULT: 0
          };
      }
      
      function convertToValidJSON(str) {
          return str
              .replace(/<[^>]*:\s*(\d+)>/g, '$1') // Remove everything in <...>, keep number after :
              .replace(/\bNone\b/g, 'null') // Replace 'None' with null
              .replace(/'/g, '"') // Optional: replace single quotes with double quotes
              .replace(/\bTrue\b/g, 'true').replace(/\bFalse\b/g, 'false') // Convert True/False to true/false
              .replace('"power"', '"power_state"') // name correction for power control
              .replace('"mode"', '"operational_mode"'); // name correction for operational mode control
      }
      
      function extractJsonFromLine(line) {
          const index = line.indexOf('{');
          if (index !== -1) {
              try {
                  const jsonStr = convertToValidJSON(line.substring(index));
                  if (LOGLEVEL > 1) log(jsonStr);
                  return JSON.parse(jsonStr);
              } catch (e) {
                  console.error(`Could not parse JSON ${e}`);
                  return null;
              }
          }
          return null;
      }
      
      // msmart-ng query 
      // usage: msmart-ng query [-h] [-d] [--region {DE,KR,US}] [--account ACCOUNT] [--password PASSWORD] [--capabilities] 
      //                        [--auto] [--energy]
      //                        [--id DEVICE_ID] [--token TOKEN] [--key KEY]
      //                        host
      function queryDevice(device) {
          const auto = (device.token == null); // query with --auto is slow, login with token,key&id it is faster
          const login = auto ? 
              ' --auto' : 
              ` --region ${region}` +
              ` --token ${device.token}` +
              ` --key ${device.key}` +
              ` --id ${device.id}`;
          const queryMsmart = msmart_ng +
              ' query' + login +
              ' --energy' +
              ` ${device.ip}`;
      
          if (LOGLEVEL > 1) log(queryMsmart);
          const devicePath = `${basePath}.${device.id}`;
          exec(queryMsmart, (error, stdout, stderr) => {
              if (error) {
                  var s = `${error}`;
                  if (s.includes('Connect failed') || s.includes('Connect timeout')) {
                      if (getState(`${devicePath}.online`).val) {
                          log(`${devicePath}.online=false`);
                          setState(`${devicePath}.online`, false, true);
                      }
                  } else {
                      console.error(`Error executing query: ${error}`);
                  }
                  return;
              }
      
              // Function to search for JSON in output
              [stdout, stderr].forEach(output => {
                  const lines = output.split('\n');
                  for (let line of lines) {
                      if (line.includes('INFO:msmart.cli:')) {
                          const data = extractJsonFromLine(line);
                          if (data) {
                              handleData(device, data);
                              break; // only the first found JSON line
                          }
                      }
                  }
              });
          });
      }
      
      /*
      const stateName = [
          {control: true,  key: 'eco', name: 'Energy Saving Mode'},
          {control: true,  key: 'power_save', name: 'Power Saving'},
          {control: true,  key: 'swing_mode', name: 'Airflow Direction'},
          {control: true,  key: 'fan_speed', name: 'Fan Speed'},
          {control: true,  key: 'operational_mode', name: 'Operating Mode'},
          {control: true,  key: 'power_state', name: 'On/Off'},
          {control: false, key: 'indoor_temperature', name: 'Indoor Temperature'},
          {control: false, key: 'outdoor_temperature', name: 'Outdoor Temperature'},
          {control: true,  key: 'target_temperature', name: 'Target Temperature'},
          {control: true,  key: 'fahrenheit', name: 'Temperature Unit'},
          {control: true,  key: 'target_humidity', name: 'Target Humidity'},
          {control: true,  key: 'horizontal_swing_angle', name: 'Horizontal Swing Angle'},
          {control: false, key: 'indoor_humidity', name: 'Indoor Humidity'},
          {control: true,  key: 'vertical_swing_angle', name: 'Vertical Swing Angle'},
          {control: true,  key: 'turbo', name: 'Turbo Mode'},
          {control: true,  key: 'freeze_protection', name: 'Frost Protection'},
          {control: true,  key: 'sleep', name: 'Sleep Mode'},
          {control: true,  key: 'display_on', name: 'Display On/Off'},
          {control: true,  key: 'beep', name: 'Beep Sound'},
          {control: false, key: 'filter_alert', name: 'Filter Warning'},
          {control: true,  key: 'follow_me', name: 'Follow Me'},
          {control: true,  key: 'purifier', name: 'Air Purifier'},
          {control: true,  key: 'self_clean', name: 'Self-Cleaning'},
          {control: false, key: 'total_energy_usage', name: 'Total Energy Usage'},
          {control: false, key: 'current_energy_usage', name: 'Current Energy Usage'},
          {control: false, key: 'real_time_power_usage', name: 'Real-Time Power Usage'},
          {control: true,  key: 'rate_select', name: 'Performance Level'},
          {control: true,  key: 'aux_mode', name: 'Auxiliary Mode'},
          {control: false, key: 'ip', name: 'IP Address'},
          {control: false, key: 'name', name: 'Device Name'},
          {control: false, key: 'supported', name: 'Supported Features'},
          {control: false, key: 'type', name: 'Device Type'},
          {control: false, key: 'online', name: 'Connection Status'},
          {control: false, key: 'port', name: 'Port'},
          {control: false, key: 'cascade_mode', name: 'Cascade Control'},   
          {control: false, key: 'sn', name: 'Serial Number'},   
      ];
      */
      const stateName = [
          {control: true,  key: 'eco', name: 'Energiesparmodus'},
          {control: true,  key: 'power_save', name: 'Energiesparen'},
          {control: true,  key: 'swing_mode', name: 'Luftstromrichtung'},
          {control: true,  key: 'fan_speed', name: 'Lüftergeschwindigkeit'},
          {control: true,  key: 'operational_mode', name: 'Betriebsmodus'},
          {control: true,  key: 'power_state', name: 'Ein/Aus'},
          {control: false, key: 'indoor_temperature', name: 'Innentemperatur'},
          {control: false, key: 'outdoor_temperature', name: 'Außentemperatur'},
          {control: true,  key: 'target_temperature', name: 'Zieltemperatur'},
          {control: true,  key: 'fahrenheit', name: 'Temperatureinheit'},
          {control: true,  key: 'target_humidity', name: 'Zielfeuchtigkeit'},
          {control: true,  key: 'horizontal_swing_angle', name: 'Horizontaler Schwenkwinkel'},
          {control: false, key: 'indoor_humidity', name: 'Raumluftfeuchtigkeit'},
          {control: true,  key: 'vertical_swing_angle', name: 'Vertikaler Schwenkwinkel'},
          {control: true,  key: 'turbo', name: 'Turbomodus'},
          {control: true,  key: 'freeze_protection', name: 'Frostschutz'},
          {control: true,  key: 'sleep', name: 'Schlafmodus'},
          {control: true,  key: 'display_on', name: 'Display Ein/Aus'},
          {control: true,  key: 'beep', name: 'Signalton'},
          {control: false, key: 'filter_alert', name: 'Filterwarnung'},
          {control: true,  key: 'follow_me', name: 'Follow Me'},
          {control: true,  key: 'purifier', name: 'Luftreiniger'},
          {control: true,  key: 'self_clean', name: 'Selbstreinigung'},
          {control: false, key: 'total_energy_usage', name: 'Gesamtenergieverbrauch'},
          {control: false, key: 'current_energy_usage', name: 'Aktueller Energieverbrauch'},
          {control: false, key: 'real_time_power_usage', name: 'Echtzeitleistung'},
          {control: true,  key: 'rate_select', name: 'Leistungsstufe'},
          {control: true,  key: 'aux_mode', name: 'Zusatzmodus'},
          {control: false, key: 'ip', name: 'IP-Adresse'},
          {control: false, key: 'name', name: 'Gerätename'},
          {control: false, key: 'supported', name: 'Unterstützt'},
          {control: false, key: 'type', name: 'Gerätetyp'},
          {control: false, key: 'online', name: 'Verbindungsstatus'},
          {control: false, key: 'port', name: 'Port'},
          {control: false, key: 'cascade_mode', name: 'Kaskadensteuerung'},   
          {control: false, key: 'sn', name: 'Seriennummer'},   
      ];
      
      function initControlSettings(device) {
          device.controlSettings = [];
          const devicePath = `${basePath}.${device.id}`;
          const controlStates = stateName.filter(state => state.control);
          controlStates.forEach(state => {
              const statePath = `${devicePath}.${state.key}`;
              device.controlSettings.push(statePath);
          });
          log('initControlSettings() device.controlSettings.length=' + device.controlSettings.length);
      }
      
      function handleData(device, data) {
          const id = data.id ? data.id.toString() : 'device';
          const devicePath = `${basePath}.${id}`;
      
          Object.keys(data).forEach(key => {
              const value = data[key];
              var keyL = key.toLowerCase();
              if (keyL === 'id') {
                  if (device.id == null) device.id = value;
                  return;
              } else if (keyL === 'key') {
                  if (device.key == null) device.key = value;
                  return;
              } else if (keyL === 'token') {
                  if (device.token == null) device.token = value;
                  return;
              }       
              if (['sn', 'name'].includes(keyL) && (value == null)) {
                  return;
              }
              const statePath = `${devicePath}.${key}`;
      
              // Configuration for createState
              const stateOptions = {
                  type: typeof value,
                  name: stateName.find(item => item.key === keyL)?.name || key,
                  write: stateName.find(item => item.key === keyL)?.control || false,
                  read: true,
              };
              if (value != null) stateOptions.def = value;
      
              // Additional properties based on the key
              if (typeof value !== 'boolean') {
                  if (keyL.includes('temperature')) {
                      stateOptions.unit = '°C';
                      stateOptions.role = 'value.temperature';
                      stateOptions.type = 'number';
                  } else if (keyL.includes('humidity')) {
                      stateOptions.unit = '%';
                      stateOptions.role = 'value.humidity';
                      stateOptions.min = 0;
                      stateOptions.max = 100;
                      stateOptions.type = 'number';
                  } else if (keyL.includes('energy')) {
                      stateOptions.unit = 'Wh';
                      stateOptions.min = 0;
                      stateOptions.max = 999999999;
                      stateOptions.type = 'number';
                  } else if (keyL.includes('power')) {
                      stateOptions.unit = 'W';
                      stateOptions.role = 'value.power';
                      stateOptions.min = 0;
                      stateOptions.max = 4000;
                      stateOptions.type = 'number';
                  }
              }
      
              // Create state if it does not exist
              createState(statePath, stateOptions, () => {
                  // After creation, get the value and update if necessary
                  getState(statePath, (err, state) => {
                      if (err || !state) {
                          setState(statePath, value, true);
                      } else {
                          if (state.val !== value) {
                              if (LOGLEVEL > 1) log(`Updating ${statePath} to ${value}`);
                              setState(statePath, value, true);
                          }
                      }
                  });
              });
          });
          if ((device.controlSettings.length == 0) && (device.id != null)) {
              initControlSettings(device);
              if (controlListener && typeof controlListener === 'function') controlListener(); // remove old listener
              controlListener = on({id: mideaPortaSplit.controlSettings, change: 'any'}, function (obj) {
                  var parts = obj.id.split('.');
                  var setting = parts[4];
                  if ((setting == 'online') && obj.state.val) powerStateOnRepeat = -1;
                  if (obj.state.ack) return; // change was made by script, ignore
                  if (LOGLEVEL > 0) log(`Changed ${obj.id} to ${obj.state.val}`);
                  controlDevice(mideaPortaSplit, setting ,obj.state.val);
              });        
          }
      }
      
      // msmart-ng control
      // usage: msmart-ng control [-h] [-d] [--region {DE,KR,US}] [--account ACCOUNT] [--password PASSWORD] 
      //                          [--capabilities] 
      //                          [--auto] 
      //                          [--id DEVICE_ID] [--token TOKEN] [--key KEY]
      //                          host setting=value [setting=value ...]
      var powerStateOnRepeat = -1;
      function controlDevice(device, setting, value) {
          if (LOGLEVEL) log(`Controlling device ${device.id}, setting ${setting}=${value}`);
      
          const stateEntry = stateName.find(entry => entry.key === setting);    
          if (!stateEntry || stateEntry.control === false) {
              if (LOGLEVEL > 1) log(`${setting} is not controllable!`);
              return;
          }
      
          if ((setting == 'power_state') && (value == false)) {
              powerStateOnRepeat = -1;
              setTimeout(function () {
                  queryDevice(device);
                  setTimeout(function () {
                      queryDevice(device);
                  }, 30 * 1000);   
              }, 30 * 1000);   
          }
      
          var pyValue = value;
          if (typeof pyValue == 'boolean') {
              pyValue = value == true ? 'True':'False';
          }
      
          const controlMsmart = msmart_ng +
              ' control' +
              ` --region ${region}` +
              ` --token ${device.token}` +
              ` --key ${device.key}` +
              ` --id ${device.id}` +
              ` ${device.ip}` +
              ` ${setting}=${pyValue}`;
      
          if (LOGLEVEL > 1) log(controlMsmart);
          const devicePath = `${basePath}.${device.id}`;
          exec(controlMsmart, (error, stdout, stderr) => {
              if (error) {
                  var s = `${error}`;
                  if (s.includes('Connect failed') || s.includes('Connect timeout')) {
                      if (getState(`${devicePath}.online`).val) {
                          log(`${devicePath}.online=false`);
                          setState(`${devicePath}.online`, false, true);
                      }
                      if ((setting == 'power_state') && (powerStateOnRepeat < (25 * 1000))) {
                          setTimeout(function () {
                              log('Repeating control: power_state=True');
                              controlDevice(device, setting, value);
                              powerStateOnRepeat += 2 * 1000;
                          }, 2 * 1000);                    
                      }
                  } else {
                      console.error(`Error executing control: ${error}`);
                  }
                  return;
              }
              powerStateOnRepeat = -1;
              // Funktion, um nach JSON zu suchen
              [stdout, stderr].forEach(output => {
                  if (output.length) {
                      if (output.includes('ERROR:')) {
                          console.error(`Error during execution: ${output}`);
                          if (getState(`${devicePath}.online`).val)
                              setState(`${devicePath}.online`, false, true);
                      } else {
                          if (LOGLEVEL > 1) log(output);
                          if (getState(`${devicePath}.online`).val == false)
                              setState(`${devicePath}.online`, true, true);
                      }
                  }
              });
          });
      }
      
      function initVar() {
          createState(msmartLoglevel, undefined, false, {
              name: 'Loglevel',
              type: 'number',
              def: LOGLEVEL,
              role: 'state'
          });
          LOGLEVEL = getState(msmartLoglevel).val;
      }
      
      // Main:
      initVar();
      queryDevice(mideaPortaSplit);
      schedule("*/2 * * * *", function () { // every 2 minutes
          queryDevice(mideaPortaSplit); 
      });
      
      // Events:
      on({id: msmartLoglevel, change: 'any'}, function (obj) {
          // Log level changed
          log(`msmartLoglevel is now ${obj.state.val}`);
          LOGLEVEL = obj.state.val;
      });
      

      Die generierten Objekte im ioBroker sehen dann so aus:
      ksnip_20250706-122153.png
      Und in meiner smartVisu (ja, ich benutze smartVisu!) sieht das so aus:
      Handy:
      photo_2025-07-06_12-15-56.jpg
      photo_2025-07-06_12-07-46.jpg
      photo_2025-07-06_12-08-18.jpg
      photo_2025-07-06_12-13-42.jpg
      Tablet:
      ksnip_20250706-123230.png

      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @jolly
      Die "Midea cloud" ist bei mir gesperrt, also ohne email & pw (war nur zum WLAN einrichten nötig).
      Ich habe es so gemacht:
      msmart-ng query --region DE --auto 192.168.1.34

      dann bekommst du ein token, key und id

      mit diesen dann control aufrufen:

      msmart-ng control --region DE --token abcabcabcc05bab57aad3833ce247729d2f880e6fd5b8e1d2ca0eec82395d7edb85cf70d339faf7d0c8baf3b8275d86b183d430347bae6eba4a009cb38d1147f --key abcabcabcd854aa6ba7b200174327ed7fc9fb0fd0032407992403b9e4104c1d3 --id 999832117233304 192.168.1.34 power_state=False

      Gruß Uwe

      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @bananajoe
      @BananaJoe
      Ja, das ist die normale Formatierung bei JavaScript mit Variablen.
      Zur Sicherheit nochmal hier den Code mit leichten Verbesserungen (leider ändert der code-tag den Sourcecode, also die {1} ignorieren!):

      /*
          Steuert eine Midea-Klimaanlage direkt über das Python-Programm 'msmart-ng' (siehe unten Installation 'msmart-ng') lokal im WLAN.
          
          Das Gerät wurde einmalig mit der Android-App in das WLAN integriert. 
          Anschließend wurde der Internetzugang für diese Gerät über die FritzBox deaktiviert, um eine Fremdsteuerung zu unterbinden.
          Keine Cloud erforderlich für dieses JavaScript!
      
          Dieses JavaScript übernimmt folgende Funktionen:  
          - Es liest die aktuellen Werte des Geräts im lokalen Netzwerk ab, siehe dazu Variable 'mideaPortaSplit'.  
            Variable 'mideaPortaSplit' muss entsprechend geändert werden. Dazu id, ip, token und key entsprechend ändern.
          - Es erstellt eigenständig die passenden Objekte in ioBroker (unter javascript.0.midea.*).  
          - Wird ein schreibbares Objekt geändert, so schreibt das JavaScript die Änderung direkt ins Gerät, 
            indem es die Befehle über 'msmart-ng' sendet.
            Gültige Werte für FanSpeed / OperationalMode / SwingMode / SwingAngle / RateSelect / BreezeMode / AuxHeatMode
            siehe Variable 'AirConditioner'.
          - Der Loglevel (javascript.0.media.loglevel) kann während der Laufzeit des Skripts angepasst werden. 
            Mögliche Werte sind 0=aus, 1=minimal, 2=alles.
      
          Idee abgeleitet aus den Beitrag: https://forum.iobroker.net/topic/33198/test-adapter-midea-dimstal-klimaanlagen-v0-0-x/346?lang=de
      
          Installation 'msmart-ng':
          =========================
          Zum Benutzer ioBroker wechseln:
              sudo -u iobroker /usr/bin/bash
          In das Home-Verzeichnis des Benutzers ioBroker wechseln
              cd ~
          Python Environment anlegen (falls noch nicht vorhanden):
              python3 -m venv python-venv
          und in die Umgebung wechseln:
              source python-venv/bin/activate
          Jetzt kann man per pip das Modul installieren
              pip install msmart-ng
          und dann per
              msmart-ng
          Nutzen. Vor der Nutzung muss dann aber immer erst das Envirtonment geladen werden.
          Intelligenter weise wird das in den nachinstallierten Python-Modulen gleich richtig hinterlegt:
              which msmart-ng
          Ausgabe:
              /home/iobroker/python-venv/bin/msmart-ng
          Inhalt:
              cat /home/iobroker/python-venv/bin/msmart-ng
          Die erste Zeile ist
              #!/home/iobroker/python-venv/bin/python3
          Womit die richtige Umgebung genutzt wird.
          In ioBroker Skripten den ganzen Pfad aufrufen:
              /home/iobroker/python-venv/bin/msmart-ng
      */
      
      // id + token + key ermittelbar über 'msmart-ng query --region DE --auto 192.168.178.205'
      const mideaPortaSplit = { 
          ip: '192.168.178.205',
          id: '999832117233304',
          token: 'BadBad132c05bab57aad3833ce247729d2f880e6fd5b8e1d2ca0eec82395d7edb85cf70d339faf7d0c8baf3b8275d86b183d430347bae6eba4a009cb38d1147f',
          key: 'BadBadc06c854aa6ba7b200174327ed7fc9fb0fd0032407992403b9e4104c1d3',
          controlSettings: [], // temp. Speicher für alle änderbaren Objekte, für on({id: device.controlSettings, change: 'any'}...
      };
      
      const basePath = 'javascript.0.midea'; // Basis-Objektpfad
      var LOGLEVEL = 2; // 0=aus, 1=minimal, 2=alles
      const msmartLoglevel = basePath + '.loglevel';
      const region = 'DE'; // --region {DE,KR,US}
      const msmart_ng = '/home/iobroker/python-venv/bin/msmart-ng';
      
      // enums siehe https://github.com/mill1000/midea-msmart/blob/main/msmart/device/AC/device.py
      class AirConditioner {
          static FanSpeed = {
              AUTO: 102,
              MAX: 100,
              HIGH: 80,
              MEDIUM: 60,
              LOW: 40,
              SILENT: 20,
              DEFAULT: 102
          };
      
          static OperationalMode = {
              AUTO: 1,
              COOL: 2,
              DRY: 3,
              HEAT: 4,
              FAN_ONLY: 5,
              SMART_DRY: 6,
              DEFAULT: 5
          };
      
          static SwingMode = {
              OFF: 0x0,
              VERTICAL: 0xC,
              HORIZONTAL: 0x3,
              BOTH: 0xF,
              DEFAULT: 0
          };
      
          static SwingAngle = {
              OFF: 0,
              POS_1: 1,
              POS_2: 25,
              POS_3: 50,
              POS_4: 75,
              POS_5: 100,
              DEFAULT: 0
          };
      
          static RateSelect = {
              OFF: 100,
              GEAR_50: 50,
              GEAR_75: 75,
              LEVEL_1: 1,
              LEVEL_2: 20,
              LEVEL_3: 40,
              LEVEL_4: 60,
              LEVEL_5: 80,
              DEFAULT: 100
          };
      
          static BreezeMode = {
              OFF: 1,
              BREEZE_AWAY: 2,
              BREEZE_MILD: 3,
              BREEZELESS: 4,
              DEFAULT: 1
          };
      
          static AuxHeatMode = {
              OFF: 0,
              AUX_HEAT: 1,
              AUX_ONLY: 2,
              DEFAULT: 0
          };
      }
      
      function convertToValidJSON(str) {
          str = str.replace(/<[^>]*:\s*(\d+)>/g, '$1'); // Entfernt alles in <...>, Zahl nach : bleibt erhalten
          str = str.replace(/\bNone\b/g, 'null'); // Ersetzt 'None' durch null
          str = str.replace(/'/g, '"'); // Optional: Ersetze einzelne Anführungszeichen durch doppelte
          str = str.replace(/\bTrue\b/g, 'true').replace(/\bFalse\b/g, 'false'); // Ersetze True/False durch true/false
          str = str.replace('"power"', '"power_state"'); // Korrektur power control
          return str;
      }
      
      function extractJsonFromLine(line) {
          const index = line.indexOf('{');
          if (index !== -1) {
              try {
                  const jsonStr = convertToValidJSON(line.substring(index));
                  if (LOGLEVEL > 1) log(jsonStr);
                  return JSON.parse(jsonStr);
              } catch (e) {
                  console.error('JSON konnte nicht geparst werden' + e);
                  return null;
              }
          }
          return null;
      }
      
      // msmart-ng query 
      // usage: msmart-ng query [-h] [-d] [--region {DE,KR,US}] [--account ACCOUNT] [--password PASSWORD] [--capabilities] 
      //                        [--auto] 
      //                        [--id DEVICE_ID] [--token TOKEN] [--key KEY]
      //                        host
      function queryDevice(device) {
          const queryMsmart = msmart_ng +
              ' query' + 
              ` --region ${region}` +
              ` --token ${device.token}` +
              ` --key ${device.key}` +
              ` --id ${device.id}` +
              ` ${device.ip}`;
      
          if (LOGLEVEL > 1) log(queryMsmart);
      
          exec(queryMsmart, (error, stdout, stderr) => {
              if (error) {
                  console.error(`Fehler beim Ausführen: ${error}`);
                  return;
              }
      
              // Funktion, um nach JSON zu suchen
              [stdout, stderr].forEach(output => {
                  const lines = output.split('\n');
                  for (let line of lines) {
                      if (line.includes('INFO:msmart.cli:')) {
                          const data = extractJsonFromLine(line);
                          if (data) {
                              handleData(device, data);
                              break; // nur die erste gefundene JSON-Zeile
                          }
                      }
                  }
              });
          });
      }
      
      function handleData(device, data) {
          const installOnControlSettings = (device.controlSettings.length == 0);
          const id = data.id ? data.id.toString() : 'device';
          const devicePath = `${basePath}.${id}`;
      
          Object.keys(data).forEach(key => {
              var keyL = key.toLowerCase();
              if (keyL === 'id') return;
              if (keyL === 'sn') return;
              if (keyL === 'key') return;
              if (keyL === 'token') return;
              
              const value = data[key];
              const statePath = `${devicePath}.${key}`;
      
              // Konfiguration für createState
              var isControl = true;
              if ((keyL === 'ip') ||
                  (keyL === 'online') ||
                  (keyL === 'port') ||
                  (keyL === 'type') ||
                  (keyL === 'name')) {
                  isControl = false;
              }
              const stateOptions = {
                  type: typeof value,
                  name: key,
                  read: true,
              };
      
              // Zusätzliche Eigenschaften basierend auf dem Schlüssel
              if (typeof value !== 'boolean') {
                  if (keyL.includes('temperature')) {
                      stateOptions.unit = '°C';
                      stateOptions.role = 'value.temperature';
                      stateOptions.type = 'number';
                      if (!keyL.includes('target_'))
                          isControl = false;
                  } else if (keyL.includes('humidity')) {
                      stateOptions.unit = '%';
                      stateOptions.role = 'value.humidity';
                      stateOptions.min = 0;
                      stateOptions.max = 100;
                      stateOptions.type = 'number';
                      if (!keyL.includes('target_'))
                          isControl = false;
                  } else if (keyL.includes('energy')) {
                      stateOptions.unit = 'Wh';
                      stateOptions.min = 0;
                      stateOptions.max = 999999999;
                      stateOptions.type = 'number';
                      isControl = false;
                  } else if (keyL.includes('power')) {
                      stateOptions.unit = 'W';
                      stateOptions.role = 'value.power';
                      stateOptions.min = 0;
                      stateOptions.max = 4000;
                      stateOptions.type = 'number';
                      isControl = false;
                  }
              }
              stateOptions.write = isControl;
              if (value != null) stateOptions.def = value;
      
              // State erstellen, falls nicht vorhanden
              createState(statePath, stateOptions, () => {
                  // Nach Erstellung Wert holen und ggf aktualisieren
                  getState(statePath, (err, state) => {
                      if (err || !state) {
                          setState(statePath, value, true);
                      } else {
                          if (state.val !== value) {
                              if (LOGLEVEL > 1) log(`${statePath}:${value}`);
                              setState(statePath, value, true);
                          }
                      }
                  });
              });
              if (installOnControlSettings && 
                  stateOptions.write && 
                  !device.controlSettings.includes(statePath)) {
                  device.controlSettings.push(statePath);
              }
          });
          if (installOnControlSettings) {
              // Events
              on({id: device.controlSettings, change: 'any'}, function (obj) {
                  if (obj.state.ack) return; // Diese Änderung wurde vom Skript selbst gemacht, ignorieren
                  if (LOGLEVEL > 0) log(`geändert ${obj.id} auf ${obj.state.val}`);
                  var parts = obj.id.split('.');
                  controlDevice(device, parts[4] ,obj.state.val);
              });
          }
      }
      
      // msmart-ng control
      // usage: msmart-ng control [-h] [-d] [--region {DE,KR,US}] [--account ACCOUNT] [--password PASSWORD] 
      //                          [--capabilities] 
      //                          [--auto] 
      //                          [--id DEVICE_ID] [--token TOKEN] [--key KEY]
      //                          host setting=value [setting=value ...]
      function controlDevice(device, setting, value) {
          if (LOGLEVEL > 0) log(`control ${device.id}, setting ${setting}=${value}`);
      
          var pyValue = value;
          if (typeof pyValue == 'boolean') {
              pyValue = value == true ? 'True':'False';
          }
      
          const controlMsmart = msmart_ng +
              ' control' +
              ` --region ${region}` +
              ` --token ${device.token}` +
              ` --key ${device.key}` +
              ` --id ${device.id}` +
              ` ${device.ip}` +
              ` ${setting}=${pyValue}`;
      
          if (LOGLEVEL > 1) log(controlMsmart);
      
          exec(controlMsmart, (error, stdout, stderr) => {
              if (error) {
                  console.error(`Fehler beim Ausführen: ${error}`);
                  return;
              }
      
              // Funktion, um nach JSON zu suchen
              [stdout, stderr].forEach(output => {
                  if (output.includes('ERROR:')) {
                      console.error(`Fehler beim Ausführen: ${output}`);
                  }
              });
          });
      }
      
      function initVar() {
          createState(msmartLoglevel, undefined, false, {
              name: 'Loglevel',
              type: 'number',
              def: LOGLEVEL,
              role: 'state'
          });
          LOGLEVEL = getState(msmartLoglevel).val;
      }
      
      // Main:
      initVar();
      queryDevice(mideaPortaSplit);
      schedule("*/5 * * * *", function () { // alle 5 Minuten
          queryDevice(mideaPortaSplit); 
      });
      
      // Events:
      on({id: msmartLoglevel, change: 'any'}, function (obj) {
          // Loglevel geändert
          log(`msmartLoglevel ist ${obj.state.val}`);
          LOGLEVEL = obj.state.val;
      });
      
      
      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      @homoran
      Danke für den Hinweis. Ich bin da vorsichtig. Leider ändert der code-tag den Sourcecode an manchen Stellen, also der gibt den Code nicht 1:1 wieder der eingeben wurde.

      posted in Tester
      U
      uweabc
    • RE: Test Adapter Midea Dimstal Klimaanlagen v0.0.x

      Ich habe vor einiger Zeit mal ein JavaScript für msmart-ng gebastelt. Dies habe ich mit den Erkenntnissen von BananaJoe neu überarbeitet. Anbei das JavaScript. midea.js

      Steuert eine Midea-Klimaanlage direkt über das Python-Programm 'msmart-ng' lokal im WLAN.

      Das Gerät wurde einmalig mit der Android-App in das WLAN integriert.
      Anschließend wurde der Internetzugang für diese Gerät über die FritzBox deaktiviert, um eine Fremdsteuerung zu unterbinden.
      Keine Cloud erforderlich für dieses JavaScript!

      Dieses JavaScript übernimmt folgende Funktionen:
      - Es liest die aktuellen Werte des Geräts im lokalen Netzwerk ab, siehe dazu Variable 'mideaPortaSplit'.
      Variable 'mideaPortaSplit' muss entsprechend geändert werden. Dazu id, ip, token und key entsprechend ändern.
      - Es erstellt eigenständig die passenden Objekte in ioBroker (unter javascript.0.midea.*).
      - Wird ein schreibbares Objekt geändert, so schreibt das JavaScript die Änderung direkt ins Gerät,
      indem es die Befehle über 'msmart-ng' sendet.
      Gültige Werte für FanSpeed / OperationalMode / SwingMode / SwingAngle / RateSelect / BreezeMode / AuxHeatMode
      siehe Variable 'AirConditioner'.
      - Der Loglevel (javascript.0.media.loglevel) kann während der Laufzeit des Skripts angepasst werden.
      Mögliche Werte sind 0=aus, 1=minimal, 2=alles.

      posted in Tester
      U
      uweabc
    • RE: IOBroker mit Smartvisu

      Bei basic.flip true,false einfach weglassen.
      Ob man nun true, false oder 1,0 oder 'true','false' in den Widgets (z.B. basic.checkbox) verwendet sollte kein Unterschied machen, da die Typenkonvertierung in smartVISU 3.3.0 dies wieder korrigiert. Also wenn ioBroker ein boolean liefert so schreibt smartVISU 3.3.0 auch ein boolean wieder zurück.

      Ich habe dazu eine Objekt definiert:

      {
        "common": {
          "name": "boolean Test",
          "type": "boolean",
          "def": false,
          "role": "state"
        },
        "native": {},
        "type": "state",
        "_id": "0_userdata.0.boolean_value",
        "acl": {
          "object": 1636,
          "state": 1636,
          "owner": "system.user.admin",
          "ownerGroup": "system.group.administrator"
        },
        "from": "system.adapter.admin.0",
        "user": "system.user.admin",
        "ts": 1671443159460
      }
      

      In einer smartVISU Testseite die zu testenden Widgets definiert:

        <div class="block">
          <div class="set-2" data-role="collapsible-set" data-theme="c" data-content-theme="a" data-mini="true">
            <div data-role="collapsible" data-collapsed="false">
              <h3>boolean value test</h3>
                basic.checkbox {{ basic.checkbox('', '0_userdata.0.boolean_value', 'boolean', true, false) }}<br>
      	  basic.stateswitch {{ basic.stateswitch('', '0_userdata.0.boolean_value', 'icon', [true,false], ['jquery_plus.svg', 'jquery_minus.svg']) }}<br>
      	  basic.flip {{ basic.flip('flip', '0_userdata.0.boolean_value') }}<br>
      	  {{ basic.print('', '0_userdata.0.boolean_value', '%s' , 'VAR==1?"true":"false"') }}<br>
            </div>
          </div>
        </div>
      

      Und dies getestet:
      ioBroker_smartVisu_boolean.gif

      Dies sieht man in Log (ioBroker):

      socketio.0 2022-12-21 19:19:49.419	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":true,"ack":false,"ts":1671646789416,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646789416}
      socketio.0 2022-12-21 19:19:47.064	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":false,"ack":false,"ts":1671646787061,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646787061}
      socketio.0 2022-12-21 19:19:44.001	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":true,"ack":false,"ts":1671646783998,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646783998}
      socketio.0 2022-12-21 19:19:41.201	silly	States user redis pmessage 0_userdata.0.boolean_value/0_userdata.0.boolean_value:{"val":false,"ack":false,"ts":1671646781198,"q":0,"from":"system.adapter.socketio.0","user":"system.user.admin","lc":1671646781198}```
      posted in ioBroker Allgemein
      U
      uweabc
    • RE: [VERKAUFT]Long Range CC2538 + CC2592 ZigBee 3 USB Stick V5

      Thread beendet

      posted in Marktplatz
      U
      uweabc
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo