Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Einsteigerfragen
    4. Einbindung von Geräten
    5. Qcells / Solax Pv Anlage live Datenabfrage via Curl

    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

    Qcells / Solax Pv Anlage live Datenabfrage via Curl

    This topic has been deleted. Only users with topic management privileges can see it.
    • jamakr4
      jamakr4 last edited by

      Hallo,
      alle die eine Solax bzw Qcells Pv Anlage haben kennen bestimmt das Problem, dass die Daten welche man über die Cloud bekommt nur alle 5 Minuten aktualisiert werden. Das ist für meine Zwecke jedoch zu ungenau. Also kurz gesucht und siehe da es gibt eine Lösung welche wesentlich mehr Daten in einem wesentlich kürzeren Zeitintervall ausgibt:

      curl -d "optType=ReadRealTimeData&pwd=<XXX Passwort XXX>" http://<XXX IP Adresse XXX>

      Als Folge kommt dann dieses tolle Zahlen Chaos (wahrscheinlich in json) raus:

      {"sn":"XXXXXXXX","ver":"3.008.10","type":14,"Data":[2342,2297,2364,55,54,54,1269,1229,1268,3766,4949,3130,21,91,1067,2852,4996,5000,4998,2,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1341,0,0,0,0,42780,0,0,4262,0,0,1,49,2425,256,7685,6672,5893,100,0,42,0,0,0,0,0,0,0,0,0,0,0,0,0,11156,0,385,4,0,0,2833,0,3235,0,31,100,12045,0,471,0,0,0,44032,0,16875,0,2755,0,220,0,0,0,0,0,0,0,0,0,1,99,1,32,122,256,4672,3200,0,300,242,218,34,33,24,2132,782,15934,15934,15934,15934,0,0,3358,3321,44242,9,20564,12339,18753,12599,18737,12356,14132,20564,12339,18754,12345,18742,12358,12599,20564,12339,18754,12345,18742,12870,14132,20564,12339,18754,12345,18742,12870,12338,20564,12339,18754,12345,18742,12358,13110,4097,4098,1281,259,0,42780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"Information":[XXXXXX,XXX,"XXXXXXXXXXX",8,1.30,0.00,1.28,1.09,0.00,1]}

      (XXX ersetzt hier nur Zahlen, welche ich nicht veröffentlichen möchte)

      Auf Github hat jemand die Zahlen dann mit diesem Skript auseinander gepuzzelt (welcher Wert bedeutet was)

      import voluptuous as vol
      import aiohttp
      from solax.inverter import InverterPost
      from solax.units import Total, Units
      from solax.utils import (
      div10,
      div100,
      twoway_div10,
      to_signed,
      pv_energy,
      twoway_div100,
      total_energy,
      discharge_energy,
      charge_energy,
      feedin_energy,
      consumption,
      )

      class QVOLTHYBG33P(InverterPost):
      """
      QCells
      Q.VOLT HYB-G3-3P
      """

      class Processors:
          """
          Postprocessors used only in the QVOLTHYBG33P inverter sensor_map.
          """
      
          @staticmethod
          def inverter_modes(value, *_args, **_kwargs):
              return {
                  0: "Waiting",
                  1: "Checking",
                  2: "Normal",
                  3: "Off",
                  4: "Permanent Fault",
                  5: "Updating",
                  6: "EPS Check",
                  7: "EPS Mode",
                  8: "Self Test",
                  9: "Idle",
                  10: "Standby",
              }.get(value, f"unmapped value '{value}'")
      
          @staticmethod
          def battery_modes(value, *_args, **_kwargs):
              return {
                  0: "Self Use Mode",
                  1: "Force Time Use",
                  2: "Back Up Mode",
                  3: "Feed-in Priority",
              }.get(value, f"unmapped value '{value}'")
      
      def __init__(self, host, port, pwd=""):
          super().__init__(host, port, pwd)
          self.manufacturer = "Qcells"
      
      _schema = vol.Schema(
          {
              vol.Required("type"): vol.All(int, 14),
              vol.Required("sn"): str,
              vol.Required("ver"): str,
              vol.Required("Data"): vol.Schema(
                  vol.All(
                      [vol.Coerce(float)],
                      vol.Length(min=200, max=200),
                  )
              ),
              vol.Required("Information"): vol.Schema(
                  vol.All(vol.Length(min=10, max=10))
              ),
          },
          extra=vol.REMOVE_EXTRA,
      )
      
      @classmethod
      def response_decoder(cls):
          return {
              "Network Voltage Phase 1": (0, Units.V, div10),
              "Network Voltage Phase 2": (1, Units.V, div10),
              "Network Voltage Phase 3": (2, Units.V, div10),
              "Output Current Phase 1": (3, Units.A, twoway_div10),
              "Output Current Phase 2": (4, Units.A, twoway_div10),
              "Output Current Phase 3": (5, Units.A, twoway_div10),
              "Power Now Phase 1": (6, Units.W, to_signed),
              "Power Now Phase 2": (7, Units.W, to_signed),
              "Power Now Phase 3": (8, Units.W, to_signed),
              "AC Power": (9, Units.W, to_signed),
              "PV1 Voltage": (10, Units.V, div10),
              "PV2 Voltage": (11, Units.V, div10),
              "PV1 Current": (12, Units.A, div10),
              "PV2 Current": (13, Units.A, div10),
              "PV1 Power": (14, Units.W),
              "PV2 Power": (15, Units.W),
              "Grid Frequency Phase 1": (16, Units.HZ, div100),
              "Grid Frequency Phase 2": (17, Units.HZ, div100),
              "Grid Frequency Phase 3": (18, Units.HZ, div100),
              "Inverter Operation mode": (19, Units.NONE, cls.Processors.inverter_modes),
              # 20 - 32: always 0
              # 33: always 1
              # instead of to_signed this is actually 34 - 35,
              # because 35 =  if 34>32767: 0 else: 65535
              "Exported Power": (34, Units.W, to_signed),
              # 35: if 34>32767: 0 else: 65535
              # 36 - 38    : always  0
              "Battery Voltage": (39, Units.V, div100),
              "Battery Current": (40, Units.A, twoway_div100),
              "Battery Power": (41, Units.W, to_signed),
              # 42: div10, almost identical to [39]
              # 43: twoway_div10,  almost the same as "40" (battery current)
              # 44: twoway_div100, almost the same as "41" (battery power),
              # 45: always 1
              # 46: follows PV Output, idles around 44, peaks at 52,
              "Power Now": (47, Units.W, to_signed),
              # 48: always 256
              # 49,50: [49] + [50] * 15160 some increasing counter
              # 51: always 5634
              # 52: always 100
              # 53: always 0
              # 54: follows PV Output, idles around 35, peaks at 54,
              # 55-67: always 0
              "Total Energy": (68, Total(Units.KWH), total_energy),
              "Total Energy Resets": (69),
              # 70: div10, today's energy including battery usage
              # 71-73: 0
              "Total Battery Discharge Energy": (74, Total(Units.KWH), discharge_energy),
              "Total Battery Discharge Energy Resets": (75),
              "Total Battery Charge Energy": (76, Total(Units.KWH), charge_energy),
              "Total Battery Charge Energy Resets": (77),
              "Today's Battery Discharge Energy": (78, Units.KWH, div10),
              "Today's Battery Charge Energy": (79, Units.KWH, div10),
              "Total PV Energy": (80, Total(Units.KWH), pv_energy),
              "Total PV Energy Resets": (81),
              "Today's Energy": (82, Units.KWH, div10),
              # 83-85: always 0
              "Total Feed-in Energy": (86, Total(Units.KWH), feedin_energy),
              "Total Feed-in Energy Resets": (87),
              "Total Consumption": (88, Total(Units.KWH), consumption),
              "Total Consumption Resets": (89),
              "Today's Feed-in Energy": (90, Units.KWH, div100),
              # 91: always 0
              "Today's Consumption": (92, Units.KWH, div100),
              # 93-101: always 0
              # 102: always 1
              "Battery Remaining Capacity": (103, Units.PERCENT),
              # 104: always 1
              "Battery Temperature": (105, Units.C),
              "Battery Remaining Energy": (106, Units.KWH, div10),
              # 107: always 256 or 0
              # 108: always 3504
              # 109: always 2400
              # 110: around rise to 300 if battery not full, 0 if battery is full
              # 112, 113: range [250,350]; looks like 113 + offset = 112,
              #   peaks if battery is full
              # 114, 115: something around 33; Some temperature?!
              # 116: increases slowly [2,5]
              # 117-121: 1620	773	12850	12850	12850
              # 122-124: always 0
              # 125,126: some curve, look very similar to "42"(Battery Power),
              # with offset around 15
              # 127,128 resetting counter /1000, around battery charge + discharge
              # 164,165,166 some curves
              "Battery Operation mode": (168, Units.NONE, cls.Processors.battery_modes),
              # 169: div100 same as [39]
              # 170-199: always 0
          }
      
      @classmethod
      async def make_request(cls, host, port=80, pwd="", headers=None):
      
          url = f"http://{host}:{port}/"
          data = f"optType=ReadRealTimeData&pwd={pwd}"
      
          async with aiohttp.ClientSession() as session:
              async with session.post(url, headers=headers, data=data) as req:
                  resp = await req.read()
      
          return cls.handle_response(resp)
      

      Nun ist meine Idee die Werte aus der Curl Abfrage einfach in ioBroker Datenpunkte einzutragen, leider kenne ich mich mit der Materie noch zu wenig aus und wollte daher mal fragen ob eventuell hier jemand eine Idee hat.

      Viele Grüße
      Jan

      arteck 1 Reply Last reply Reply Quote 0
      • arteck
        arteck Developer Most Active @jamakr4 last edited by

        @jamakr4 schau dir axios mal an..damit kannst du den curl absetzen und die daten empfangen..
        dann musst du den json zerlegen..

        1 Reply Last reply Reply Quote 0
        • Meister Mopper
          Meister Mopper last edited by

          @jamakr4

          Ich arbeite mit dem Solax Adapter und kann damit die Daten lokal z. B. im 10-Sekundentakt abfragen. Die cloud benötige ich gar nicht.

          jamakr4 1 Reply Last reply Reply Quote 0
          • jamakr4
            jamakr4 @Meister Mopper last edited by

            @meister-mopper Danke

            K 1 Reply Last reply Reply Quote 0
            • K
              kgw @jamakr4 last edited by

              @jamakr4
              siehe hier:
              Solax Photovoltaik Portal in ioBroker

              https://forum.iobroker.net/topic/13152/solax-photovoltaik-portal-in-iobroker/10

              evtl. nützt es dir was.

              1 Reply Last reply Reply Quote 0
              • First post
                Last post

              Support us

              ioBroker
              Community Adapters
              Donate

              865
              Online

              31.9k
              Users

              80.2k
              Topics

              1.3m
              Posts

              4
              5
              840
              Loading More Posts
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes
              Reply
              • Reply as topic
              Log in to reply
              Community
              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
              The ioBroker Community 2014-2023
              logo