Navigation

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

    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

    T
    • Profile
    • Following 0
    • Followers 0
    • Topics 25
    • Posts 97
    • Best 1
    • Groups 1

    thomassch

    @thomassch

    0
    Reputation
    51
    Profile views
    97
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    thomassch Follow
    Starter

    Best posts made by thomassch

    • IOBroker Update von js-controller unter Windows (gelöst)

      Hallo Zusammen,

      ich entschuldige mich schon mal für die dumme Frage - aber wie kann ich den js-controller updaten unter Windows.
      Die im Update beschriebene Vorgehensweise

      Variante 1 - Windows
      Für das Updaten von ioBroker auf Windows den entsprechenden Installer mit der gewünschten js-controller-Version von der Download-Seite https://www.iobroker.net/#de/download herunterladen und mit diesem das Update vornehmen. Mit dem Windows Installer können auch vorher manuell installierte Server oder Installationen von anderen Betriebssystemen nach Windows migriert und geupdated werden.
      
      Variante 2 - Windows (manuell installiert)
      Eine manuelle Installation erfolgt mit Administrator-Rechten. Bitte deshalb ein cmd.exe-Kommandozeilenfenster als Administrator starten (mit Rechtsklick auf cmd.exe und "Ausführen als Administrator") und dort folgende Befehle ausführen:
      
      cd C:\iobroker (oder wo ioBroker installiert wurde)
      iobroker stop, um den ioBroker Service zu stoppen
      iobroker status, um zu prüfen, ob ioBroker beendet ist
      iobroker update
      iobroker upgrade self
      ioBroker Service starten oder Rechner rebooten, danach sollte ioBroker neu starten und man kann sicher sein das alle alten Prozesse beendet waren.~~~~
      

      habe ich versucht. Bei Variante 1 mittels Setup muss ich wohl eine neue Instanz anlegen und die Daten werden dann übertragen. Allerdings ist das
      schon sehr aufwendig da ich ja "nur" den js-controller updaten möchte.
      Mit dem manuellen Update habe ich unter CMD Fenster die Fehlermeldung dass zu.B. iobroker update nicht unterstützt wird.

      Irgendwas mache ich hier falsch oder stelle mich einfach mal dumm an.

      Wie mache ich das unter Windows richtig?

      Gruss
      Thomas

      posted in ioBroker Allgemein
      T
      thomassch

    Latest posts made by thomassch

    • RE: Frage : Migrate MySQL nach Influxdb

      Hallo Zusammen,

      erst mal vielen Dank an @JackGruber für das Script, es hat mir viel Arbeit erspart.
      Da ich eine Microsoft SQL Datenbank haben, musste ich das Script etwas umschreiben (sorry @JackGruber ).

      Falls jemand diese Änderung benötigt, hier ist sie:

      1. Ihr benötigt Python, ich habe diese Version installiert
        https://www.python.org/downloads/release/python-3125/

      2. Die Jason Datei wie folgt ergänzen. Ich habe Sie als migrateMSQL.py umbenannt:
        Bitte MSQL Login Daten entsprechend anpassen <xxxxx> und auch für die Influx Datenbank die Zugangsdaten anpassen. Hier ist es wichtig das Token zu verwenden das man
        bei INfluxDB V2 anlegen muss.
        Bei mir ist InfluxDB ein extra Container im Proxmox und daher musste ich hier auch noch die IP Adresse angeben.

      {
        "MSQL": {
          "server": "localhost",
          "user": "iobroker",
          "password": "xxxxxxxx",
          "database": "iobroker"
        },
        "MySQL": {
          "host": "localhost",
          "port": 3306,
          "database": "iobroker",
          "user": "iobroker",
          "password": "iobroker"
        },
        "InfluxDB": {
          "host": "192.168.2.xxx",
          "ssl": false,
          "port": 8086,
          "database": "iobroker",
          "retention_policy": "autogen",
          "user": "admin",
          "password": "7TBAUCsxxxxxY2Sde9QAiAYTDo0WzwerJ8BqfOvxxxx19a8jwYzociuB_4RFVGIDAkN7MA==",
          "store_ack_boolean": true
        }
      }
      
      1. Bitte dann die PYMSSQL Bibliothek installieren, diese wird für den Zugriff auf MSQL benötigt.
        Ich habe das in der Commandozeile unter einem Windows Betriebsystem gemacht, in dieser Reihenfolge:
      pip install -r requirements.txt
      pip install pymssql
      
      1. Achtet darauf, dass Ihr im IOBroker die InfluxDB Schnittstelle zusätzlich zu euren SQL Interface installiert und ich musste leider für alle Datenpunkte die InfluxDB Protokollierung einzeln aktivieren und ein
        stellen. Da die InfluxDB Schnittstelle keine individuelle Löschung pro Datenpunkte erlaubt, habe ich 2 InfluxDB Instanzen installiert mit unterschiedlichen Löschzeiten (eigentlich eine für unbegrenzt und eine für 1 Jahr).
        Hier werde ich noch schauen was InfluxDB kann, soweit ich weiß sollte man das in Influx direkt programmieren und damit entsprechende Daten verdichten bzw. löschen.

      2. Und nun das Phyton Script ausführen, hier gibt es ein paar Anpassungen wegen MSQL z.B. "import pymssql", wie Ihr unten im geänderten SourceCode seht.
        Ich habe bewusst darauf verzichtet meine Änderungen "schön zu machen", da ich es nur einmalig brauche, aber wichtig für mich war, es funktioniert.
        Die Ausführung kann sehr sehr lange dauern, daher habt Geduld. Damit Ihr die Scriptausgaben auch seht, nicht einfach auf migrateMSQL.py klicken, sonst geht das Command Fenster sofort wieder zu.
        Öffnet am Besten ein CMD, wechselt in der Verzeichnis wo Ihr requirements.txt und migrateMSQL.py abgelegt habt und gebt dann folgende Zeile ein.

      python migrateMSQL.py ALL
      

      Und hier nun der Inhalt von migrateMSQL.py:

      import json
      import os
      import sys
      import time
      import pymssql
      
      try:
          from influxdb import InfluxDBClient
          import pymssql
      except Exception as ex:
          print(ex)
          print("Please install all requirements!")
          sys.exit(1)
      
      if not sys.version_info >= (3, 6):
          print("Python version to old!")
          print(sys.version)
          sys.exit(1)
      
      # Load DB Settings
      database_file = os.path.join(os.path.dirname(
          os.path.realpath(__file__)), "database.json")
      if not os.path.exists(database_file):
          print("Please rename database.json.example to database.json")
          sys.exit(1)
      
      f = open(database_file, 'r')
      db = f.read()
      f.close()
      
      try:
          db = json.loads(db)
      except json.decoder.JSONDecodeError as ex:
          print(database_file + "Json is not valid!")
          print(ex)
          sys.exit(1)
      except Exception as ex:
          print("Unhandeld Exception")
          print(ex)
          sys.exit(1)
      
      try:
          print("SQL CONNECT: server="+db['MSQL']['server'])
          MSSQL_CONNECTION = pymssql.connect(server=db['MSQL']['server'],
                                             user=db['MSQL']['user'],
                                             password=db['MSQL']['password'],
                                             database=db['MSQL']['database'],
      					as_dict=True)
      
      #    MYSQL_CONNECTION = pymysql.connect(host=db['MySQL']['host'],
      #                                       port=db['MySQL']['port'],
      #                                       user=db['MySQL']['user'],
      #                                       password=db['MySQL']['password'],
      #                                       db=db['MySQL']['database'])
      
      
      except pymssql.OperationalError as error:
          print(error)
          sys.exit(1)
      except Exception as ex:
          print("MSSQL connection error")
          print(ex)
          sys.exit(1)
      
      
      INFLUXDB_CONNECTION = InfluxDBClient(host=db['InfluxDB']['host'],
                                           ssl=db['InfluxDB']['ssl'],
                                           verify_ssl=True,
                                           port=db['InfluxDB']['port'],
                                           username=db['InfluxDB']['user'],
                                           password=db['InfluxDB']['password'],
                                           database=db['InfluxDB']['database'])
      
      # Select datapoints
      if len(sys.argv) > 1 and sys.argv[1].upper().strip() == "ALL":
          MIGRATE_DATAPOINT = ""
          print("Migrate ALL datapoints ...")
      elif len(sys.argv) == 2:
          MIGRATE_DATAPOINT = " AND name LIKE '" + sys.argv[1] + "' "
          print("Migrate '" + sys.argv[1] + "' datapoint(s) ...")
      else:
          print("To migrate all datapoints run '" + sys.argv[0] + " ALL'")
          print("To migrate one datapoints run '" + sys.argv[0] + " <DATAPONTNAME>'")
          print("To migrate a set of datapoints run '" +
                sys.argv[0] + ' "hm-rega.0.%"' + "'")
          sys.exit(1)
      print("")
      
      # dictates how columns will be mapped to key/fields in InfluxDB
      SCHEMA = {
          "time_column": "time",  # the column that will be used as the time stamp in influx
          # columns that will map to fields
          "columns_to_fields": ["ack", "q", "from", "value"],
          # "columns_to_tags" : ["",...], # columns that will map to tags
          # table name that will be mapped to measurement
          "table_name_to_measurement": "name",
      }
      
      DATATYPES = ["float", "string", "boolean"]
      
      #####
      # Generates an collection of influxdb points from the given SQL records
      #####
      def generate_influx_points(datatype, records):
          influx_points = []
          for record in records:
              #tags = {},
              fields = {}
              # for tag_label in SCHEMA['columns_to_tags']:
              #   tags[tag_label] = record[tag_label]
              for field_label in SCHEMA['columns_to_fields']:
                  if db['InfluxDB']['store_ack_boolean'] == True:
                      if field_label == "ack":
                          if (record[field_label] == 1 or record[field_label] == "True" or record[field_label] == True):
                              record[field_label] = True
                          else:
                              record[field_label] = False
      
                  fields[field_label] = record[field_label]
                  
                  # Daten in richtigen Typ wandeln
                  if field_label == "value":
                      if datatype == 0: # ts_number
                          fields["value"] = float(record["value"] or 0)
                      elif datatype == 1: # ts_string
                          fields["value"] = str(record["value"])
                      elif datatype == 2: # ts_bool
                          fields["value"] = bool(record["value"])
      
              influx_points.append({
                  "measurement": record[SCHEMA['table_name_to_measurement']],
                  # "tags": tags,
                  "time": record[SCHEMA['time_column']],
                  "fields": fields
              })
      
          return influx_points
      
      
      def query_metrics(table):
          MSSQL_CURSOR.execute(
              "SELECT name, id, type FROM datapoints WHERE id IN(SELECT DISTINCT id FROM " + table + ")" + MIGRATE_DATAPOINT)
          rows = MSSQL_CURSOR.fetchall()
          print('Total metrics in ' + table + ": " + str(MSSQL_CURSOR.rowcount))
          return rows
      
      
      def migrate_datapoints(table):
          query_max_rows = 100000  # prevent run out of mermory limit on SQL DB
          process_max_rows = 1000
      
          migrated_datapoints = 0
          metrics = query_metrics(table)
          metric_nr = 0
          metric_count = str(len(metrics))
          processed_rows = 0
          for metric in metrics:
              metric_nr += 1
              print(metric['name'] + "(ID: " + str(metric['id']) + ", type: " + DATATYPES[metric['type']] + ")" +
                    " (" + str(metric_nr) + "/" + str(metric_count) + ")")
      
              start_row = 0
              processed_rows = 0
              while True:
                  query = """SELECT d.name,
                      m.ack AS ack,
                      CAST(m.q AS FLOAT) AS q,
                      s.name AS [from],
                      m.val AS value,
                      CAST(m.ts * 1000000 AS BIGINT) AS time
                      FROM [dbo].[""" + table + """] AS m
                      LEFT JOIN [dbo].[datapoints] AS d ON m.id = d.id
                      LEFT JOIN [dbo].[sources] AS s ON m._from = s.id
                      WHERE m.q = 0 AND d.id = """ + str(metric['id']) + """
                      ORDER BY m.ts DESC
                      OFFSET """ + str(start_row) + """ ROWS 
                      FETCH NEXT """ + str(query_max_rows) + """ ROWS ONLY; """
      #### alte query für MySQL
      #            query = """SELECT d.name,
      #                                m.ack AS 'ack',
      #                                (m.q*1.0) AS 'q',
      #                                s.name AS "from",
      #                                m.val AS 'value',
      #                                (m.ts*1000000) AS'time'
      #                                FROM """ + table + """ AS m
      #                                LEFT JOIN datapoints AS d ON m.id=d.id
      #                                LEFT JOIN sources AS s ON m._from=s.id
      #                                WHERE q=0 AND d.id = """ + str(metric['id']) + """
      #                                ORDER BY m.ts desc
      #                                LIMIT """ + str(start_row) + """, """ + str(query_max_rows)
      #
                  MSSQL_CURSOR.execute(query)
                  if MSSQL_CURSOR.rowcount == 0:
                      break
      
                  # process x records at a time
                  while True:
                      selected_rows = MSSQL_CURSOR.fetchmany(process_max_rows)
                      if len(selected_rows) == 0:
                          break
      
                      print(f"Processing row {processed_rows + 1:,} to {processed_rows + len(selected_rows):,} from LIMIT {start_row:,} / {start_row + query_max_rows:,} " +
                            table + " - " + metric['name'] + " (" + str(metric_nr) + "/" + str(metric_count) + ")")
                      migrated_datapoints += len(selected_rows)
      
                      try:
                          INFLUXDB_CONNECTION.write_points(generate_influx_points(metric['type'], 
                              selected_rows), retention_policy=db['InfluxDB']['retention_policy'])
                      except Exception as ex:
                          print("InfluxDB error")
                          print(ex)
                          sys.exit(1)
      
                      processed_rows += len(selected_rows)
      
                  start_row += query_max_rows
              print("")
      
          return migrated_datapoints
      
      
      #MSSQL_CURSOR = MSSQL_CONNECTION.cursor(cursor=pymssql.cursors.DictCursor)
      MSSQL_CURSOR = MSSQL_CONNECTION.cursor()
      migrated = 0
      migrated += migrate_datapoints("ts_number")
      migrated += migrate_datapoints("ts_bool")
      migrated += migrate_datapoints("ts_string")
      print(f"Migrated: {migrated:,}")
      
      
      MSSQL_CONNECTION.close()
      
      1. Ausgeführt

      Final habe ich damit 45,770,061 Datensätzen auf einmal migrieren können und stichprobenartig mal über die Weboberfläche von INfluxDB geprüft ob soweit alles passt, noch ist mir kein Fehler aufgefallen.

      Ich hoffe diese Anleitung hilft denen weiter die statt mySQL ein MSSQL verwenden.

      Danke nochmals an @JackGruber für die tolle Arbeit.

      Gruss
      Thomas

      posted in ioBroker Allgemein
      T
      thomassch
    • RE: SQL Timeout von 15 sek erhöhen

      @thomassch

      Für die die die procedure interessiert

      USE [iobroker]
      GO
      /****** Object:  StoredProcedure [dbo].[usp_CopyNewHoursValuesTable]    Script Date: 22.06.2023 21:52:48 ******/
      SET ANSI_NULLS ON
      GO
      SET QUOTED_IDENTIFIER ON
      GO
      -- =============================================
      -- Author:		Thomas Schatz
      -- Create date: 26.01.2023
      -- Description:	procedure für das Ermitteln der Differenzwerte pro Stunde
      -- =============================================
      -- ein paar sammlungen von guten Abfragen
      -- 		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy') as xYear, 
      		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM') as xMonth, 
      		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM-dd') as xDay, 
      		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM-dd HH') AS xLastDayHour, 
      		--FORMAT(dateadd(s,l.ts/1000,'19700101'),'yy-MM-dd HH:mm:ss') AS xTimeSec,
      -- =============================================
      -- VERSION
      -- V5.0  ... inklusive löschen der Werte in IOBroker Werte die älter sind als 1 Tag
      -- 
      
      ALTER PROCEDURE [dbo].[usp_CopyNewHoursValuesTable] 
      	-- Add the parameters for the stored procedure here
      	@ClearAll INT = 0, -- 1 == löscht die letzten x-Tage, -1 läöscht dann alle Werte in der Tabell usr_IOBroker_Werte komplett
      	@RunWithoutCopy INT = 1, -- 1== es wird nur angezeigt aber nichts kopiert
      	@Debug int = 0, -- bei 1 werden alle Debugs angezeigt
      	@DebugOnlyObject varchar(100) ='',
      	@MaxDays INT = 1,-- maximale Anzahl der zu kopierenden Werte, damit die Abfragezeit nicht zu gross wird
      	@StartDate datetime = '',
      	@EndDate datetime = ''
      AS
      BEGIN
      	-- SET NOCOUNT ON added to prevent extra result sets from
      	-- interfering with SELECT statements.
      	SET NOCOUNT ON;
      
      	-- sicherstellen das die Procedure nicht 2x läuft (1x IOBeroker Script und einmal hier im SQL Exec)
      	BEGIN TRANSACTION
      
          -- Insert statements for procedure here
      	DECLARE @xStartDate DATETIME, @xStartDateMin DATETIME, @xEndDate DATETIME, @xNewestDate DATETIME, @xNewest_IOWerte DATETIME, @xOldest_tsNumber DATETIME, @xOldest_IOWerte DATETIME;
      	DECLARE @xTempDateTime DATETIME, @xTemp_Datetime DATETIME;
      	DECLARE @xTempBigInt BIGINT;
      	DECLARE @xStartDateUNIX BIGINT, @xEndDateUNIX BIGINT
      	DECLARE @RunTime DATETIME;
      	DECLARE @NewAnzahl as int, @NewAnzahl1 as int;
      	DECLARE @myId as int;
      	DECLARE @bNewest as bigint;
      	DECLARE @OldValuesCount as bigint, @OldValuesCountBeforeDelete as bigint, @NewValuesCount as bigint;
      	Declare @xOldest_ref as bigint;
      	DECLARE @xNewest_IOWerte_AddDays as datetime;
      	DECLARE @CountAnzahl as int, @runtimestart as datetime;
      	DECLARE @CurrentTime as bigint;
      
      	-- wurd ein Filterobject übergeben
      	set @myId=0
      	if (@DebugOnlyObject<>'') 
      	BEGIN
      		Select 'Es wurde ein FilterObject übergeben'
      		select @DebugOnlyObject
      		Select @myId = id from datapoints where name=@DebugOnlyObject
      	END
      
      	-- Tabelle erstellen, falls nicht extiert
      	IF  NOT EXISTS (SELECT * FROM sys.objects 
      	WHERE object_id = OBJECT_ID(N'[dbo].[usr_IOBroker_Werte]') AND type in (N'U'))
      	BEGIN
      		CREATE TABLE dbo.usr_IOBroker_Werte (
      			id int not NULL,
      			create_ts bigInt,
      			UnixTime bigint,
      			min_ts bigint,
      			max_ts bigint,
      			Zaehler real,
      			[DateTime] datetime,
      			Diff real,
      			CONSTRAINT IOBroker_WerteIndex UNIQUE  (id,min_ts)
      		)
      		CREATE NONCLUSTERED INDEX [NonClusteredIndex-Test_UNIXtime_ID] ON [dbo].[usr_IOBroker_Werte]
      		(
      			[id] ASC,
      			[UnixTime] DESC,
      			[DateTime] DESC
      		)
      		select 'Tabelle mit Index erstellt'
      	END
      
      	
      
      	DROP TABLE IF EXISTS #tempWERTE01	
      	CREATE TABLE #tempWERTE01 (
      		xRowCount int NOT NULL,
      		xId int NOT NULL,
      		xUnixTime bigint NOT NULL,
      		min_ts bigint NULL,
      		max_ts bigint NULL,
      		xZaehler real NULL,
      		CONSTRAINT tempWERTE01_Index UNIQUE  (xid,xUnixTime)
      	)
      	CREATE NONCLUSTERED INDEX ix_tempWERTE01 ON #tempWERTE01 ([xId],[xUnixTime] DESC);
      
      
      	DROP TABLE IF EXISTS #tempWERTE02	
      	CREATE TABLE #tempWERTE02 (
      		xId int NOT NULL,
      		xUnixTime bigint NOT NULL,
      		min_ts bigint NULL,
      		max_ts bigint NULL,
      		xZaehler real NULL,
      		xDiff real NULL,
      		CONSTRAINT tempWERTE02_Index UNIQUE  (xid,xUnixTime)
      	)
      	CREATE NONCLUSTERED INDEX ix_tempWERTE02 ON #tempWERTE02 ([xId],[xUnixTime] DESC,[min_ts]);
      
      
      	
      	-- falls die Tabelle geloescht werden soll
      	if (@ClearAll=-1) 
      	BEGIN
      		if (EXISTS (select TOP 1 1 from usr_IOBroker_Werte))
      		BEGIN
      			if @Debug>0 Select 'IOBroker Werte (Alle) werden alle gelöscht TRUNCATE'
      			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte vor loeschen' from dbo.usr_IOBroker_Werte 
      			TRUNCATE TABLE dbo.usr_IOBroker_Werte
      			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte nach loeschen' from dbo.usr_IOBroker_Werte 
      		END
      	END	
      
      	-- falls xTage von Tabelle geloescht werden sollen
      	if (@ClearAll>0) 
      	BEGIN
      		if (EXISTS (select TOP 1 1 from usr_IOBroker_Werte))
      		BEGIN
      			if @Debug>0 Select 'IOBroker Werte (x-Tage) werden alle gelöscht TRUNCATE'
      			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte vor loeschen' from dbo.usr_IOBroker_Werte 
      			-- nun die x-Tage loeschen
      			--select @xNewest_IOWerte=dateadd(SECOND,max(UnixTime)/1000, '01.01.1970 00:00:00.0') from usr_IOBroker_Werte
      			select @xNewest_IOWerte=dateadd(SECOND,max(UnixTime)/1000, '01.01.1970 00:00:00.0') from usr_IOBroker_Werte
      			select @xTemp_Datetime=Dateadd(day,-@ClearAll,DATETIMEFROMPARTS(YEAR(@xNewest_IOWerte),MONTH(@xNewest_IOWerte),DAY(@xNewest_IOWerte),0,0,0,0))
      			select @xTempBigInt=DATEDIFF(SECOND,'01.01.1970 00:00:00.0',@xTemp_Datetime)
      			if @Debug>0 Select @xNewest_IOWerte as 'Neuste Werte in Tabelle @xNewest_IOWerte=:'
      			if @Debug>0 Select @xTemp_Datetime as 'Loesche alles Älter als@xTemp_Datetime=:'
      			if @Debug>0 Select @xTempBigInt as 'Sekunden für Delete Abfrage @xTempBigInt=:'
      
      			if @RunWithoutCopy=0
      			BEGIN
      				DELETE from usr_IOBroker_Werte
      				where
      					UnixTime/1000>=@xTempBigInt
      					AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
      			END
      			if @Debug>0 select count(*) as 'Anzahl Werte in IOBroker_Werte nach loeschen' from dbo.usr_IOBroker_Werte 
      			if @Debug>2
      			BEGIN
      				select 
      					FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(UnixTime),'yy-MM-dd HH:mm:ss') as ts_lesbar_UTC,
      					* 
      				from usr_IOBroker_Werte
      				where
      					UnixTime/1000>=@xTempBigInt
      					AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
      			END
      
      		END
      	END	
      
      	-- schauen wir mal ob IOBorker_Werte mnoch leer ist
      	if (NOT EXISTS (select TOP 1 1 from usr_IOBroker_Werte))
      	BEGIN
      	    -- IOBroker leer
      	    if @Debug>0 select 'der Neueste Wert in der Tabelle usc_IOBroker_Werte ist NULL, daher jetzt mal den ältesten Wert in ts_number suchen'
      	    set @xOldest_tsNumber=(select dbo.fn_Convert_UNIX_2_DateTime(min(ts)) from ts_number);
      	    if @Debug>0 select @xOldest_tsNumber as 'Wir nehmen als Startwert den Wert von in ts_number:'
      	    SET @xStartDate= @xOldest_tsNumber
      		-- als EndeDatum setzen wir Startdatum plus die Anzahl der Tage die kopiert werden dürfen laut Übergabe
      		SET @xEndDate=dateadd(day,@MaxDays, @xStartDate)
      		if @Debug>0 select (@MaxDays) as 'Anzahl der Tage die kopiert werden sollen:'
      	END
      	ELSE
      	BEGIN
      		-- Werte in IOBroker vorhanden
      		if @Debug>0 select @MaxDays as 'MaxDays:'
      		
      		-- ermitteln wir wieviele Werte in der Tabelle stehen
      		set @OldValuesCountBeforeDelete=(select count(*) from dbo.usr_IOBroker_Werte)
      
      		-- wir leoschen mal den letzte Stunde in der IOBorkerWerte Tabelle, der sollte meist nur angefangen sein und keine volle Stunde beinhalten
      		select @xNewest_IOWerte=dateadd(SECOND,max(UnixTime)/1000, '01.01.1970 00:00:00.0') from usr_IOBroker_Werte
      		if @Debug>0 select @xNewest_IOWerte as '@xNewest_IOWerte='
      		if @Debug>0 select dateadd(hour, -1,GETUTCDATE()) as 'dateadd(hour, -1,GETUTCDATE())='
      		
      		if @xNewest_IOWerte>=dateadd(hour, -1,GETUTCDATE())
      		begin
      			if @Debug>0 
      			BEGIN
      				select 'wir loeschenletzte stunde, das wären dann:'
      				
      				SELECT dateadd(SECOND,UnixTime/1000, '01.01.1970 00:00:00.0'),* from usr_IOBroker_Werte
      				where
      					UnixTime/1000>DATEDIFF(SECOND,'01.01.1970 00:00:00.0',Dateadd(hour,-1,@xNewest_IOWerte))
      					AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
      			END
      			
      			DELETE from usr_IOBroker_Werte
      			where
      				UnixTime/1000>DATEDIFF(SECOND,'01.01.1970 00:00:00.0',Dateadd(hour,-1,@xNewest_IOWerte))
      				AND id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
      		END
      		
      		select @xNewest_IOWerte=dbo.fn_Convert_UNIX_2_DateTime(max(min_ts)) from usr_IOBroker_Werte
      		if @Debug>0 select @xNewest_IOWerte as 'usr_IOBroker_Werte vorhanden, hier ist der neueste Wert min_ts:'
      
      		set    @xNewest_IOWerte_AddDays=dateadd(day,@MaxDays,@xNewest_IOWerte)
      		if @Debug>0 select @xNewest_IOWerte_AddDays as 'neuester Wert von usr_IOBroker_Werte + MaxDays:'
      		
      		select @xOldest_ref=dbo.fn_Convert_DateTime_2_ts_sec(@xNewest_IOWerte_AddDays)
      		if @Debug>0 select @xOldest_ref as '@xOldest_ref:'
      		
      		select @xOldest_tsNumber=ISNULL((select dbo.fn_Convert_UNIX_2_DateTime(min(ts)) from ts_number where ts/1000>@xOldest_ref),GETUTCDATE())
      		if @Debug>0 select @xOldest_tsNumber as 'Der älterste Wert von ts_number der größer ist als der neuste IOBroker_Wert Eintrag + MaxDays:'
      
      		SET @xStartDate=dateadd(day,-1, @xNewest_IOWerte)
      		SET @xEndDate=@xOldest_tsNumber
      	END
      	
      	-- falls Start und Ende übergeben, dann machen wir nur das
      	if @StartDate<>'' 
      	BEGIn
      		if @Debug>0 select 'Start und Ende übergeben, Abfrage auf diese Werte begrenzen' 
      		SET @xStartDate=@StartDate
      		SET @xEndDate=@EndDate
      	END
      
      
      /*
      	--- schauen wir mal welche number_ts das betrift
      	if (@Debug>0) 
      	BEGIN
      		select 
      			dbo.fn_Convert_ts_sec2DateTime(ts/1000),
      			* 
      		from ts_number
      		where 
      			(ts/1000) >= @xStartDateUNIX
      			and (ts/1000) <  @xEndDateUNIX
      			and id = (CASE WHEN @myId=0 THEN id ELSE @myId END)
      		order by ts DESC
      	END
      
      	-- Welches Messwwerte schauen wir an?
      
      	if (@Debug>0) 
      	BEGIN
      		select 'ts_number, diese Werte schauen wir an'
      		
      		select 
      			ts as xts,
      			dbo.fn_Convert_UNIX_2_UTC(ts) as ts_in_UTC,
      			FORMAT(dateadd(s,ts/1000,'19700101'),'yy-MM-dd HH:mm:ss') as ts_in_Format_ohne_UTC,
      			@xStartDate as xStartFilter_ts,
      			dbo.fn_ConvertUTC2Local(@xStartDate) as xStartFilter_UTC,
      			@xEndDate as xEndeFilter_ts,
      			dbo.fn_ConvertUTC2Local(@xEndDate) as x@xEndeFilter_UTC,
      			*
      		from ts_number
      		where
      			id = @myId
      			AND ts >= dbo.fn_ConvertUTC2IOBrokerTS(@xStartDate)
      			AND ts <  dbo.fn_ConvertUTC2IOBrokerTS(@xEndDate)
      		order by ts DESC;
      	END
      	*/
      	set @runtimestart=getUTCdate()
      	set @CountAnzahl=0
      
      	while (@CountAnzahl=0 and datediff(SECOND,@runtimestart,getUTCdate())<30)
      	begin
      	if @Debug>0 select 'while schleife startr'
      	if @Debug>0 select  datediff(SECOND,@runtimestart,getUTCdate()) as 'laufzeit'
      
      		-- wir loeschen mal die temporären Tabellen
      		TRUNCATE TABLE #tempWERTE01
      		TRUNCATE TABLE #tempWERTE02
      
      		-- berechnen wir enddatum
      		if @xEndDate>GETUTCDATE()	
      		BEGIN
      			if @Debug>0 select 'Endedatum ist größer als aktuelles Datum, daher mal begrenzen auf aktuelles Datum!'
      			set @xEndDate=GETUTCDATE()
      		END
      	
      		if @Debug>0 select @xStartDate as 'Filter Startzeit'
      		if @Debug>0 select @xEndDate   as 'Filter Endezeit';
      
      		-- un nun Start un Ende als UNIXWert d.h. ohne UTC Verschiebung
      		SET @xStartDateUNIX=[dbo].[fn_Convert_DateTime_2_ts_sec](@xStartDate)
      		SET @xEndDateUNIX=[dbo].[fn_Convert_DateTime_2_ts_sec](@xEndDate)
      	
      		--select dbo.fn_Convert_ts_sec2DateTime(@xStartDateUNIX) as 'Filter @xStartDateUNIX', @xStartDateUNIX as 'as ts'
      		--select dbo.fn_Convert_ts_sec2DateTime(@xEndDateUNIX)   as 'Filter @xEndDateUNIX', @xEndDateUNIX as 'as ts'
      
      		-- und nun mal versuchen die neue Tabelle zu füllen
      		--- wir ermitteln damit nicht ein einfaches MIN oder MAX, das würde mit GROUP schon gehen, sondern
      		-- holen uns den letzten Wert des Tages aus ts_number und speichern diesen
      		-- es wird hier mit xRC doppelte Einträge in ts_number gefiltert, das kann z.B. passieren, wenn zur gleichen Zeit ein Wert vom Adapter kommt und der SQL Server einen Wert schreibt wenn er aufzeichnen soll alle x-sekunden
      
      
      		if @Debug>0 select 'Alle Objekte: ermitteln wir mal die Werte im Intervall 1 h und kopieren diese in #tempWERTE01'
      		insert into #tempWERTE01 
      		(
      			xRowCount,
      			xId, 
      			min_ts,max_ts,
      			xUnixTime,
      			xZaehler
      		)
      		select * from 
      		(
      			SELECT 
      				ROW_NUMBER() OVER(PARTITION BY l.id,l.ts ORDER BY l.ts DESC) xRC,
      				l.id as xId,
      				m.min_ts as min_ts,
      				m.max_ts as max_ts,
      				l.ts as xUnixTime,
      				l.val AS xZaehler
      			FROM ts_number l
      			INNER JOIN 
      			(
      				SELECT
      					MAX(x.id) as xid,
      					x.ts/1000/(60*60) as d,
      					MIN(x.ts) as min_ts,		
      					MAX(x.ts) as max_ts
      				FROM  ts_number x
      				Where 
      					x.id = (CASE WHEN @myId=0 THEN x.id ELSE @myId END)
      					AND (x.ts/1000) >=  @xStartDateUNIX  --AND (x.ts/1000) >= datediff(s, '1970.01.01', @xStartDateUNIX)
      					AND (x.ts/1000) < @xEndDateUNIX
      				GROUP BY 
      					x.id,
      					x.ts/1000/(60*60) -- 1 h
      			) m
      			ON (
      				l.id=m.xid
      				AND l.ts = m.max_ts
      				)
      			WHERE ---shere bezeiht sich auf den gesamten Join
      				--xRC = 1
      				l.id = (CASE WHEN @myId=0 THEN l.id ELSE @myId END)
      				And l.val IS NOT NULL
      				And l.val>=0
      				And	(l.ts/1000) >= @xStartDateUNIX
      				and (l.ts/1000) <  @xEndDateUNIX
      		) aa
      		where aa.xRC=1
      
      
      		if (@Debug>0) 
      		BEGIN
      			select 'temp01 Inhalt anzeigen'
      			select 
      				xUnixTime as xxts,
      				dbo.fn_Convert_UNIX_2_UTCDateTime(xUnixTime) as ts_in_UTC,
      				FORMAT(dateadd(s,xUnixTime/1000,'19700101'),'yy-MM-dd HH:mm:ss') as ts_in_Format_ohne_UTC,
      				@xStartDate as xStartFilter_ts,
      				dbo.fn_Convert_UTCDateTime_2_ts_sec(@xStartDate) as xStartFilter_UTC,
      				@xEndDate as xEndeFilter_ts,
      				dbo.fn_Convert_UTCDateTime_2_ts_sec(@xEndDate) as xEndeFilter_UTC,
      				*
      			from #tempWERTE01
      			order by xId  ASC, xUnixTime DESC;
      		END
      
      
      	/*
      		if (@Debug>0) 
      		BEGIN
      			select 'temp01 vor dem Löschen doppelter Werte'
      			SELECT COUNT(*) from #tempWERTE01;
      		END		
      			-- wir loeschen einfach die doppelten werte, falls IOBroker mal zu einem Zeitpunkt sowohl den Messwerte bekommt
      			-- als auch den eingestellten Wert der Aufgezeichnet werden soll im Intervall
      			-- damit verhindern wir beim Insert eine Schlüsselverletzung
      		
      		WITH cte AS (
      			SELECT 
      				xId, 
      				xUnixTime, 
      				ROW_NUMBER() OVER (
      					PARTITION BY 
      						xId, 
      						xUnixTime
      					ORDER BY 
      						xId, 
      						xUnixTime
      				) row_num
      				FROM 
      				#tempWERTE01
      		)
      		DELETE FROM cte
      		WHERE row_num > 1;
      
      		select 'temp01 NACH dem Löschen doppelter Werte'
      		select * from #tempWERTE01;
      	*/
      	
      		-- und nun mal mit der internen SQL Funktion lag - die Differenz zum vorherigen Wert ermitteln
      		--select 'und nun die Differenz immer zum letzten Wert:'
      		insert into #tempWERTE02
      		( xId, min_ts,max_ts, xUnixTime, xZaehler,xDiff )
      		SELECT 
      		  xId, min_ts,max_ts, xUnixTime, xZaehler, 
      		  round((xZaehler-lag(xZaehler) over (partition by xid order by (xUnixTime/1000/(60*60)))),3) -- 1 h 
      		  --(xZaehler-lag(xZaehler) over (partition by xid order by FORMAT(dbo.fn_Convert_UNIX_2_UTC(xUnixTime),'yy-MM-dd HH')))
      		FROM #tempWERTE01 ;
      
      		-- Werte anzeigen
      		if (@Debug>0) 
      		BEGIN
      			select 'Inhalt #tempWerte02 anzeigen:';
      			--set rowcount @MaxCount;
      			Select dbo.fn_Convert_UNIX_2_UTCDateTime(xUnixTime) as xUnixTimeUTC,
      			*
      			from #tempWERTE02
      			order by xId ASC, xUnixTime DESC
      		END;
      
      		-- unsinnige Werte anzeigen
      		if (@Debug>0) 
      		BEGIN
      			select 'Unsinnige Inhalt #tempWerte02 anzeigen:';
      			Select dbo.fn_Convert_UNIX_2_UTCDateTime(xUnixTime) as xUnixTimeUTC,
      			*
      			from #tempWERTE02
      			where xDiff<0 OR xDiff>(xzaehler*1.5)
      			order by xId ASC, xUnixTime DESC
      		END;
      		
      		-- Sprünge die keinen Sinn machen löschen
      		delete 
      			from #tempWERTE02 
      			where xDiff<0 OR xDiff>(xzaehler*1.5);
      
      		/*
      		-- versuchen wir mal einen totalen Zaehler zu bauen
      		--select 'und nun ergänzen wir einen totalen neuen laufenden Zähler:'
      		select 
      			*,
      			sum(xDiff) over(order by xDay rows unbounded preceding) as xSumTotal,
      			(select name from datapoints where id=rr.xid) as xObject
      		FROM 
      			tempWERTE02 rr;
      		*/
      
      		-- wieviele Werte wären neu?
      		with xAnzahl as (
      		SELECT DISTINCT 
      			s.xId, s.min_ts, s.max_ts, s.xUnixTime, s.xZaehler, s.xDiff	 
      		from #tempWERTE02 s
      		WHERE NOT EXISTS 
      				(SELECT *
      				FROM  dbo.usr_IOBroker_Werte t
      				WHERE 
      					t.id = s.xId
      					--AND t.UnixTime = s.xUnixTime
      					and t.min_ts = s.min_ts   --- hier mal schauen ob der Startwert schon vorhanden ist
      					--and s.xUnixTime IS NOT NULL
      					)
      		)
      		select @CountAnzahl=count(*) from xAnzahl 
      		--select @CountAnzahl=0
      		if @Debug>0 select @CountAnzahl as 'Anzahl der kopierenden werte'
      		if (@CountAnzahl=0)
      		begin
      			set @xEndDate=dateadd(day,@MaxDays,@xEndDate);
      			if @Debug>0 select @xEndDate as 'keine werte erkannt und kopiert, enddate erhöhen!'
      		end
      		else
      		begin
      			break
      		end
      
      		if @xEndDate>GETUTCDATE()	
      		BEGIN
      			if @Debug>0 select 'Endedatum ist größer als aktuelles Datum, daher mal begrenzen auf aktuelles Datum!'
      			break
      		END
      
      		if @EndDate<>''
      		begin
      			if @xEndDate>@EndDate	
      			BEGIN
      				if @Debug>0 select 'Endedatum ist größer als @EndDate, wir stoppen die Schleife!'
      				break
      			END
      		END
      
      End; -- ####### WHILE
      
      	set @OldValuesCount=(select count(*) from dbo.usr_IOBroker_Werte)
      	if (@RunWithoutCopy=0)
      	BEGIN
      		if @Debug>0 select 'Funktion mit RunWithoutCopy=0 gestartet d.h. es werden neue Werte kopiert!'
      		-- Werte in die echte neue Tabelle übernehmen
      		--select 'und nun die Werte in die neue Tabelle kopieren:'
      		set @CurrentTime = DATEDIFF(SECOND,'01.01.1970',getUTCDate())
      		if @Debug>0 select @CurrentTime as '@CurrentTime='
      
      		INSERT  INTO dbo.usr_IOBroker_Werte 
      		(
      			id, create_ts, min_ts, max_ts, UnixTime, [DateTime], Zaehler, Diff
      		)
      		SELECT DISTINCT 
      			s.xId, @CurrentTime, s.min_ts, s.max_ts, s.xUnixTime, dbo.fn_Convert_UNIX_2_UTCDateTime(s.xUnixTime), s.xZaehler, s.xDiff
      		from #tempWERTE02 s
      		WHERE NOT EXISTS 
      				(SELECT *
      				FROM  dbo.usr_IOBroker_Werte t
      				WHERE 
      					t.id = s.xId
      					AND 
      					(
      					t.UnixTime = s.xUnixTime
      					or t.min_ts = s.min_ts
      					)   --- hier mal schauen ob der Startwert schon vorhanden ist
      					--and s.xUnixTime IS NOT NULL
      				);
      	END
      	ELSE
      	BEGIN
      		if @Debug>0 select 'Funktion mit RunWithoutCopy gestartet d.h. es werden keine neuen Werte kopiert'
      	END
      
      		
      	set @NewValuesCount = (select count(*) from dbo.usr_IOBroker_Werte)
      	select 
      		@xStartDate as 'Startzeit', 
      		@xEndDate as 'Endezeit', 
      		(@NewValuesCount-@OldValuesCount) as 'Created', 
      		(@NewValuesCount-@OldValuesCountBeforeDelete) as 'New', 
      		@NewValuesCount as 'WerteIOBrokerTable'
      
      		
      	if (@Debug>=2) 
      	BEGIN
      		select 'alle werte in IOBroker_Werte anzeigen'
      		SELECT TOP 1000
      			dbo.fn_Convert_ts_sec_2_UTCDateTime(create_ts) as create_ts_UTC,
      			FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(UnixTime),'yy-MM-dd HH:mm:ss') as ts_lesbar_UTC,
      			FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(max_ts),'yy-MM-dd HH:mm:ss') as xMax_UTC,
      			FORMAT(dbo.fn_Convert_UNIX_2_UTCDateTime(min_ts),'yy-MM-dd HH:mm:ss') as xMin_UTC,
      			*
      		from usr_IOBroker_Werte
      		where
      			Id = (CASE WHEN @myId=0 THEN Id ELSE @myId END) -- DEBUG
      		order by UnixTime desc
      
      		--select count(*) as 'Anzahl Werte in IOBroker_Werte' from dbo.usr_IOBroker_Werte 
      	END;
      	
      	
      	-- wir loeschen nun alles temporäre
      	drop table #tempWERTE01
      	drop table #tempWERTE02
      
      
      	COMMIT TRANSACTION
      END
      
      
      posted in JavaScript
      T
      thomassch
    • RE: SQL Timeout von 15 sek erhöhen

      @fastfoot

      Die Indizies sind neu erstellt, das bringt nicht so viel dass ich in unter die 15 sek komme.

      Die Prozedure verdichtet Daten aus ts_number auf Stundenwerte und speichert diese dann in eine neue Tabelle, wobei ich hier immer nur die letzten 7 Tage anschaue, verdichte und kopiere, damit ich nicht immer 20 Mio Werte mit mehreren Jahren ständig berechnen muss.

      Warum verdichte ich auf Stundenwerte m? Das ist eigentlich einfach, ich zeige Tabellen in der vis an in der ich über Jason eine Anzeige der Tages, Monats und Jahresverbräuche mache. Würde ich da ständig über alle Werte gehen in ts_number, würde es zu lange dauert.

      Ich habe ganz bewusst keine Iobroker Datenpunkte erzeugt die auf Tage basieren, sondern wollte nachträglich meine alten absoluten Zählerstände verwenden können aus ts_number.
      Ich denke das Problem ist dass ich mittlerweile 20 Mio Einträge in ts_number habe und 1 Mio in der Stundentabelle die ich erzeuge, die joins sind dann schon etwas aufwendiger.

      Die procedure kann ich gerne mal posten diese ist aber sehr lang und komplex, daher wollte ich erstmal versuchen die 15 Sekunden zu erhöhen.

      Gruß
      Thomas

      posted in JavaScript
      T
      thomassch
    • SQL Timeout von 15 sek erhöhen

      Hallo Zusammen,

      ich rufe mit SendTo eine SQL procedure auf, die leider länger als 15 sek benötigt (mehr optimieren kann ich sie auch leider nicht mehr).
      Es sind einfach ca. 1 Mio Datensätze die recherchiert werden.
      Nach 15 sek. wird SendTo aber abgebrochen mit einem TimeOut Fehler.

      Gibt es irgendeine Möglichkeit diese timeout Zeit zu erhöhen oder ist das im Adapter so definiert?

      Die Fehlermeldung dazu ist:
      javascript.0 (30008) script.js.SQL_Abfragen.SQL_DeltaAbfragen: RequestError: Timeout: Request failed to complete in 15000ms

      Der Code im Script ist so:

      function SQLquery() {
          var idQuery = myQueryDelta;
          if (logging>=2) log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= '+idQuery,"info");
      
          var xStart = new Date(); // Zeit messen
          sendTo('sql.0', 'query', idQuery, function (result) {
              var xTime = (new Date() - xStart)/1000; // Zeit s messen
              if (logging>=1) log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= DAUER: '+xTime + " s / " + idQuery,"info");
              setState(idTimeResult_Duration,xTime,true);
      
              if (result.error) {
                  log(result.error);
                  log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= DAUER: '+xTime + " s / " + idQuery,"error");
              } else {
                  // show result
                  if (logging>=1) log (xfunkName +'->'+arguments.callee.name+':'+'myQuery= DAUER: '+xTime + " s / " + idQuery,"info");
                  if (logging>=1) log (xfunkName +'->'+arguments.callee.name+':'+'myQueryresultJSON= '+JSON.stringify(result.result),"info");
                  setState(idResultJson,JSON.stringify(result.result),true);
                  setState(idLastResult_CallWithoutError,formatDate(xStart, "TT.MM.JJJJ hh:mm:ss"),true);
              }
          });
      }
      

      Danke für jeden Tipp dazu.,

      Gruss
      Thomas

      posted in JavaScript
      T
      thomassch
    • RE: ePaper Statusdisplay Hausflur

      Hallo @draexler ,
      schade aber ok, dachte mir schon das der ESP32 hier eventuell zu wenig Dampf hat.

      Gruss
      Thomas

      posted in Praktische Anwendungen (Showcase)
      T
      thomassch
    • RE: ePaper Statusdisplay Hausflur

      Hallo @draexler,

      Super Projekt, gefällt mir.
      Damit ich das Bild nicht vorher designen muss und nur werte Anzeige, würde ich gerne ein gerendertes Bild vom Iobroker auf dem epaper darstellen, hast du eine Idee wie das ginge oder wo ich suchen könnte?
      Damit könnte ich dann zb. Grafana Bilder darstellen.

      Gruß
      Thomas

      posted in Praktische Anwendungen (Showcase)
      T
      thomassch
    • RE: Selector - Filter funktioniert nicht bei Enums (gelöst)

      @paul53 ja grad mal versucht keine Änderung
      Irgendwie erkennt er den von Hand angelegten Enum nicht…

      posted in JavaScript
      T
      thomassch
    • Selector - Filter funktioniert nicht bei Enums (gelöst)

      gelöst

      ich habe folgende Selector verwendet und nun geht es:

      NEU $("state [id=*] (functions='MeldungErzeugen')");
      ALT: $("channel[state.id=*] (functions='MeldungErzeugen')");

      var cacheSelectorState    = $("state[id=*](functions=MeldungErzeugen)"); 
      
      if (logging) log(xfunkName +': Liste1 ausgeben in Logs *****************');
      if (logging) log(xfunkName +': selector: '+ cacheSelectorState.length);
      cacheSelectorState.each(function (idx,i) {
          var xxname ="";
          if (getObject(idx)) xxname=getObject(idx).common.name; else xxname=getObject(idx).id;
          if (logging) { log(xfunkName + ': i='+i+' / idx=' + idx + ' / xxname = '+xxname ); }
          //if (i == 1) return false;
      });
      

      Hallo Zusammen,

      ich habe gesucht und probiert und komme einfach nicht drauf, warum das nicht geht.
      Ich habe einen ENUM erstellt "MeldungErzeugen" und diesem einige Objekte zugewiesen.

      In der Abfrage mit JAVASCRIPT versuche ich nun alle Objekte in einem Selector zu filtern, die diese neue functions "MeldungErzeugen" haben. Auf diese will ich final dann Events einstellen, so dass ich für diese dann später gezielt Meldungen ausführe, wenn sie sich ändern.

      Allerdings scheitere ich an dem Seperator, mein Code sieht so aus:
      PS. wenn ich statt "MeldungErzeugen" mal "Geräte" eintragen ergibt das die Objekte die dieses ENUM haben.
      Filter ich nach "MeldungErzeugen" kommt nichts!

      Wäre über jeden Tipp dankbar!

      Gruss
      Thomas

      Screenshot at Nov 12 19-33-52.png

      Screenshot at Nov 12 19-37-31.png Screenshot at Nov 12 19-37-49.png

      var cacheSelectorState    = $("channel[state.id=*](functions='MeldungErzeugen')"); 
      
      if (logging) log(xfunkName +': Liste1 ausgeben in Logs');
      cacheSelectorState.each(function (idx,i) {
          var xxname ="";
          if (logging) { log(xfunkName + ': i='+i+' / idx=' + idx + ' / xxname = '+xxname); }
      });
      ```~~strikethrough text~~
      posted in JavaScript
      T
      thomassch
    • RE: Test Adapter homeconnect (BSH Home-Connect) v0.0.x

      @thomassch

      spassig, ich habe den Adapter nochmals gestoppt und dann wieder gestartet und siehe da nun hat er alle Daten vom Gerät und läuft 🙂

      posted in Tester
      T
      thomassch
    • RE: Test Adapter homeconnect (BSH Home-Connect) v0.0.x

      @bockwurst19

      bei mir auch genau das selbe, erst war die Instanz mit gelben Ausrufezeichen, dann habe ich mich manuell https://api.home-connect.com/security/oauth/device_verify?user_code=64U8-UM6R ausgeführt und dort nochmals bestätigt und dann wurde die Instanz grün.
      Leider kommt trotzdem alle 10 sek diese Meldung im Log und ich kann auch nicht nochmals über api-home-connect bestätigen da die user_code abgelaufen ist.

      homeconnect.0
      2022-10-09 09:41:48.018 info Wait 10 seconds to retry
      homeconnect.0
      2022-10-09 09:41:48.018 error {"error":"expired_token","error_description":"Device authorization session not found, expired or blocked"}
      homeconnect.0
      2022-10-09 09:41:48.018 error https://api.home-connect.com/security/oauth/device_verify?user_code=64U8-UM6R
      homeconnect.0
      2022-10-09 09:41:48.018 error Bitte überprüfe Benutzername und Passwort oder besuche diese Seite für manuelle Anmeldung:
      homeconnect.0
      2022-10-09 09:41:48.018 error Please check username and password or visit this site for manually login:

      posted in Tester
      T
      thomassch
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
    The ioBroker Community 2014-2023
    logo