Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Thingspeak - Datenabruf (https://www.delphipraxis.net/212985-thingspeak-datenabruf.html)

Schleifchen 2. Mai 2023 20:01

Thingspeak - Datenabruf
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo in die Runde, ich versuche mit
Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils,
  IdHTTP;

procedure Main;
var
  http : TIdHTTP;
  resultStr: string;
begin
  http := TIdHTTP.Create( nil );
  try
    resultStr := http.Get( 'https://api.thingspeak.com/channels/9/fields/1.json?results=10' );
  finally
    http.Free;
  end;

  Writeln( resultStr );
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;
  ReadLn;

end.
(hier im Forum gefunden) die Daten eines Channels abzurufen.
siehe: https://de.mathworks.com/help/thingspeak/readfield.html

aber leider erscheint nur eine Fehlermeldung: siehe Anhang.
Wie ist das Problem zu lösen?
Danke

Stefan

mytbo 2. Mai 2023 20:38

AW: Thingspeak - Datenabruf
 
Zitat:

Zitat von Schleifchen (Beitrag 1521927)
... die Daten eines Channels abzurufen.

Wenn es dir nur um die Daten geht, rufe die URL im Browser auf. Kopiere die JSON Daten ins Clipboard. Der JSON-Viewer kann die Daten aus dem Clipboard direkt laden.

Bis bald...
Thomas

Schleifchen 2. Mai 2023 21:44

AW: Thingspeak - Datenabruf
 
danke, dann habe ich mich falsch ausgedrückt. Ziel ist es die abgerufenen Werte in eine SQlite-Datenbank einzutragen.
Derzeit dokumentiere ich es in Excel mittels VBA.
Die URL lautet: 'https://api.thingspeak.com/channels/1671193/feeds.csv' & Appendix
wobei Appendix = 'start=Datum des letzten Eintrages' ist. Die URL sollte gleichfalls so aufgebaut sein.

Ich versuchte dieses Beispiel hier im Forum: auf Thingspeak anzuwenden. Sicherlich wird sich eine Regel finden die Daten aus 'resultStr' in die Datenbank einzubauen.

Stefan

Uwe Raabe 2. Mai 2023 21:56

AW: Thingspeak - Datenabruf
 
Welche Delphi Version?

Schleifchen 2. Mai 2023 21:58

AW: Thingspeak - Datenabruf
 
Hallo, Delphi 10.4 Version 27.0.40680.4203

Stefan

mytbo 2. Mai 2023 22:20

AW: Thingspeak - Datenabruf
 
Mit mORMot gibt es mehrere Wege. Einer ist:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.search,
  mormot.net.client;

type
  TCsvItem = packed record
    created_at: TDateTime;
    entry_id: Integer;
    field1: Double;
    field2: Double;
    field3: Double;
    field4: String;
  end;
  TCsvItems = array of TCsvItem;
 
var
  url: RawUtf8;
  content: RawByteString;
  csvItems: TCsvItems;
begin
  url := 'https://api.thingspeak.com/channels/1671193/feeds.csv?start="2023-05-02T19:20"';
  content := HttpGet(url);
  if (content <> '')
    and DynArrayLoadCsv(csvItems, content, TypeInfo(TCsvItems)) then
  begin
    var count: Integer := Length(csvItems);
    if count > 0 then
    begin
      ShowMessage(Format('Anzahl: %d', [Length(csvItems)]));
      with csvItems[0] do
        ShowMessage(Format('%s-%d-%f-%f-%f-%d' , [DateToStr(created_at), entry_id, field1, field2, field3, field4.Trim.ToInteger]));
    end;
  end;
Bis bald...
Thomas

Uwe Raabe 2. Mai 2023 22:54

AW: Thingspeak - Datenabruf
 
Willst du nun die CSV-Datei abrufen und auswerten oder die Werte des einzelnen Feldes wie im Eingangspost?

Wie ist die Struktur deiner Datenbanktabelle?

Schleifchen 2. Mai 2023 23:06

AW: Thingspeak - Datenabruf
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ach, d.h. ich muss mORMOT laden!?
Die mORMot2-master hab ich von GitHub heruntergeladen und enpackt. Anschliesend im RAD-Studio, wie unter https://github.com/synopse/mORMot2/b...ster/README.md beschrieben den Pfad gesetzt. (siehe Anhang)
Trotzdem meckert Delphi: 'mormot.core.base' nicht gefunden...

Da hab ich wohl was falsch gemacht?

Schleifchen 2. Mai 2023 23:11

AW: Thingspeak - Datenabruf
 
@Uwe: die Werte sollen in einem Array gespeichert werden, so wie im Code von Thomas :-)
Die Speicherung als csv war nur eine Zwischenlösung bedingt durch VBA.

mytbo 2. Mai 2023 23:27

AW: Thingspeak - Datenabruf
 
Zitat:

Zitat von Schleifchen (Beitrag 1521938)
Da hab ich wohl was falsch gemacht?

Installiere so wie hier beschrieben. Eintragen unter "Tools/Optionen"->"Sprache/Delphi/Bibliothek/Bibliothekspfad und Suchpfad".

Bis bald...
Thomas

Rollo62 3. Mai 2023 07:32

AW: Thingspeak - Datenabruf
 
Könnte es bei der SSL Fehlermeldung nicht einfach an fehlenden SSL DLL-Libraries oder Konfiguration liegen ?

Uwe Raabe 3. Mai 2023 08:30

AW: Thingspeak - Datenabruf
 
Zitat:

Zitat von Schleifchen (Beitrag 1521939)
@Uwe: die Werte sollen in einem Array gespeichert werden

Wie verhält sich diese Aussage zu dieser?
Zitat:

Zitat von Schleifchen (Beitrag 1521933)
Ziel ist es die abgerufenen Werte in eine SQlite-Datenbank einzutragen.


rabatscher 3. Mai 2023 10:00

AW: Thingspeak - Datenabruf
 
Dein Problem ist SSL. In deinem Code wird kein SSL handler konfiguriert - ein kleiner Check per Browser zeigt,
dass TLS1.2 dort zumindest verwendet wird. Du müsstest die SSL handler in diese Richtung konfigurieren:

function CreateCon : TIdHTTP;
begin
Result := TIdHTTP.Create(nil);
sslIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Result);
sslIOHandler.SSLOptions.Method := sslvTLSv1_2;

Result.IOHandler := sslIOHandler;
Result.ConnectTimeout := 6000;
Result.ReadTimeout := 6000;
end;


Einfacher:
Ich würde im url mal statt HTTPS:// nur HTTP:// verwenden.
Der Server unterstützt http auch ;)

himitsu 3. Mai 2023 10:28

AW: Thingspeak - Datenabruf
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1521946)
Wie verhält sich diese Aussage zu dieser?
Zitat:

Zitat von Schleifchen (Beitrag 1521933)
Ziel ist es die abgerufenen Werte in eine SQlite-Datenbank einzutragen.


Joar, nahezu für jedes DBMS gibt es Import-Funktionen für CSV,
nur leider oft über die Konsole. (selten, indem man die CSV-Daten als einen VARCHAR/TEXT übergibt)

Gut, man könnte im SQL auch den Text selber über Funktionen zerlegen und den Feldern für's INSERT übergeben,
aber die SQlite-DB liegt auch vermutlich eh auf dem selben System, wie der Client, was das Problem einfacher lösen lassen könnte.

Ja, natürlich kann man die CSV auch im Delphi-Code zerlegen und manuell Feld für Feld und Record (Zeile) für Record einzeln posten. :stupid:
OK, es wäre so bissl langsamer, da viele DB-Aufrufe, aber es würde wohl auch bissl RAM/Cache sparen, wenn man es nicht im SQL löst.

Schleifchen 3. Mai 2023 11:22

AW: Thingspeak - Datenabruf
 
Hallo, der Hinweis von rabatscher:
Zitat:

Ich würde im url mal statt HTTPS:// nur HTTP:// verwenden.
ist vorerst die einfachste Lösung und funzt auch. DANKE, hätte ich auch selber drauf kommen können :-), bin ich aber nicht :-(
Mein weiterer Plan wäre jetzt aus
Code:
resultStr
die Anweisung für die Datenbank zu erstellen.

Jetzt möchte ich bei allen Bedanken und mangels Wissen mORMot für später aufheben.

Danke
Stefan

mytbo 3. Mai 2023 16:00

AW: Thingspeak - Datenabruf
 
Zitat:

Zitat von Schleifchen (Beitrag 1521957)
Jetzt möchte ich bei allen Bedanken und mangels Wissen mORMot für später aufheben.

Ich finde, die Umsetzung mit mORMot ist einfach. Die CSV-Datei enthält Zeichen an Stellen, an dem diese bestimmt nicht hingehören. Ohne diese Überraschung wäre es ein No-Brainer. Daher folgende praktische (mit kleinen Umwegen) Lösung:
Delphi-Quellcode:
uses
  mormot.core.base,
  mormot.core.data,
  mormot.core.text,
  mormot.core.perf,
  mormot.core.search,
  mormot.core.unicode,
  mormot.core.variants,
  mormot.core.datetime,
  mormot.core.os,
  mormot.net.client,
  mormot.orm.base,
  mormot.orm.core,
  mormot.orm.sqlite3,
  mormot.rest.core,
  mormot.rest.sqlite3,
  mormot.db.raw.sqlite3,
  mormot.db.raw.sqlite3.static;
 
type
  TCsvItem = packed record
    created_at: String;
    entry_id: Integer;
    field1: Double;
    field2: Double;
    field3: Double;
    field4: String;
  end;
  TCsvItems = array of TCsvItem;

  TOrmCsvItem = class(TOrm)
  private
    FCreatedAt: TDateTime;
    FField1: Double;
    FField2: Double;
    FField3: Double;
    FField4: Integer;
  published
    property CreatedAt: TDateTime
      read FCreatedAt write FCreatedAt;
    property Field1: Double
      read FField1 write FField1;
    property Field2: Double
      read FField2 write FField2;
    property Field3: Double
      read FField3 write FField3;
    property Field4: Integer
      read FField4 write FField4;
  end;

function UpdateCsvItems(const pmcDBFileName: TFileName): Integer;
const
  BASE_URL = 'https://api.thingspeak.com/channels/1671193/feeds.csv?start=';
var
  csvItems: TCsvItems;
begin
  Result := -1;
  var restClient: TRestClientDB := TRestClientDB.Create(TOrmModel.Create([TOrmCsvItem]), Nil, pmcDBFileName, TRestServerDB, {HandleUserAuthentication=}False);
  try
    restClient.Model.Owner := restClient;
    restClient.DB.Synchronous := smOff;
    restClient.DB.LockingMode := lmExclusive;
    restClient.Server.CreateMissingTables(0, [itoNoAutoCreateGroups, itoNoAutoCreateUsers]);

    var ormItem: TOrmCsvItem := TOrmCsvItem.Create;
    try
      var startTime: TDateTime := IncYear(Now, -100);
      var maxID: TID := restClient.TableMaxID(TOrmCsvItem);
      if (maxID >= 0) and restClient.Retrieve(maxID, ormItem) then
        startTime := ormItem.CreatedAt;

      var url: RawUtf8 := BASE_URL + DateTimeToIso8601(startTime, {Expanded=}True, 'T', {WithMS=}False, '"');
      if DynArrayLoadCsv(csvItems, HttpGet(url), TypeInfo(TCsvItems)) then
      begin
        if Length(csvItems) = 0 then Exit; //=>

        restClient.BatchStart(TOrmCsvItem);
        for var i: Integer := 0 to High(csvItems) do
        begin
          if csvItems[i].entry_id <= maxID then Continue;

          with csvItems[i] do
          begin
            ormItem.IDValue := entry_id;
            ormItem.CreatedAt := Iso8601ToDateTime(StringToUtf8(created_at));
            ormItem.Field1 := field1;
            ormItem.Field2 := field2;
            ormItem.Field3 := field3;
            ormItem.Field4 := field4.Trim.ToInteger;
          end;
          restClient.BatchAdd(ormItem, True, True);
        end;

        var insRowIDs: TIDDynArray;
        if restClient.BatchSend(insRowIDs) = HTTP_SUCCESS then
          Result := Length(insRowIDs);
      end;
    finally
      ormItem.Free;
    end;
  finally
    restClient.Free;
  end;
end;
Damit sind alle Daten in der SQLite Datenbank. Auch die SQLite DB-Engine ist mit im Programm. Aufrufen kannst du die Funktion wie folgt:
Delphi-Quellcode:
var
  timer: TPrecisionTimer;
begin
  timer.Start;
  ShowMessage(Format('New insert: %d, Time: %s', [UpdateCsvItems(MakePath([Executable.ProgramFilePath, 'daten.db3'])), timer.Stop]));
Bis bald...
Thomas

Schleifchen 3. Mai 2023 17:53

AW: Thingspeak - Datenabruf
 
Hallo Thomas, ich bekomme mORMot nicht zum Laufen.
  1. habe unter GitHub die gesamte Datei curl-master.zip geladen und in den Order D:\Programme\RAD-Studio\mORMot2 entpackt.
  2. im RAD-Studio unter Tools->Sprache->Bibliotheken-> Bibliothekspfad und Suchpfad um
    Code:
    D:\Programme\RAD-Studio\mORMot2\src;D:\Programme\RAD-Studio\mORMot2\src\app;D:\Programme\RAD-Studio\mORMot2\src\core;D:\Programme\RAD-Studio\mORMot2\src\crypt;D:\Programme\RAD-Studio\mORMot2\src\db;D:\Programme\RAD-Studio\mORMot2\src\lib;D:\Programme\RAD-Studio\mORMot2\src\misc;D:\Programme\RAD-Studio\mORMot2\src\net;D:\Programme\RAD-Studio\mORMot2\src\orm;D:\Programme\RAD-Studio\mORMot2\src\rest;D:\Programme\RAD-Studio\mORMot2\src\script;D:\Programme\RAD-Studio\mORMot2\src\soa;D:\Programme\RAD-Studio\mORMot2\src\tools\ecc;D:\Programme\RAD-Studio\mORMot2\src\ui;[*]
    ergänzt.

Während des Compilierens erscheint die Fehlermeldung:
Code:
[dcc32 Fehler] mormot.lib.z.pas(603): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibdeflate.obj'
[dcc32 Fehler] mormot.lib.z.pas(604): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibtrees.obj'
[dcc32 Fehler] mormot.lib.z.pas(605): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibinflate.obj'
[dcc32 Fehler] mormot.lib.z.pas(606): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibinftrees.obj'
[dcc32 Fehler] mormot.lib.z.pas(607): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibadler32.obj'
[dcc32 Fehler] mormot.lib.z.pas(608): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibcrc32.obj'
[dcc32 Fehler] mormot.lib.z.pas(609): E1026 Datei nicht gefunden: '..\..\static\delphi\zlibinffast.obj'
[dcc32 Fehler] mormot.lib.z.pas(178): E2065 Ungenügende Forward- oder External-Deklaration: 'crc32'
[dcc32 Fehler] mormot.lib.z.pas(185): E2065 Ungenügende Forward- oder External-Deklaration: 'adler32'
[dcc32 Fehler] mormot.lib.z.pas(642): E2065 Ungenügende Forward- oder External-Deklaration: 'deflate'
[dcc32 Fehler] mormot.lib.z.pas(643): E2065 Ungenügende Forward- oder External-Deklaration: 'deflateEnd'
[dcc32 Fehler] mormot.lib.z.pas(644): E2065 Ungenügende Forward- oder External-Deklaration: 'inflate'
[dcc32 Fehler] mormot.lib.z.pas(645): E2065 Ungenügende Forward- oder External-Deklaration: 'inflateEnd'
[dcc32 Fehler] mormot.lib.z.pas(647): E2065 Ungenügende Forward- oder External-Deklaration: 'deflateInit_'
[dcc32 Fehler] mormot.lib.z.pas(649): E2065 Ungenügende Forward- oder External-Deklaration: 'inflateInit_'
[dcc32 Fehler] mormot.lib.z.pas(652): E2065 Ungenügende Forward- oder External-Deklaration: 'deflateInit2_'
[dcc32 Fehler] mormot.lib.z.pas(654): E2065 Ungenügende Forward- oder External-Deklaration: 'inflateInit2_'
[dcc32 Fehler] mormot.lib.z.pas(655): E2065 Ungenügende Forward- oder External-Deklaration: 'get_crc_table'
[dcc32 Fataler Fehler] mormot.core.zip.pas(797): F2063 Verwendete Unit 'mormot.lib.z.pas' kann nicht compiliert werden
??? sicherlich weist Du auf Anhieb was ich wiedermal vergessen habe....?:?

mytbo 3. Mai 2023 18:16

AW: Thingspeak - Datenabruf
 
Zitat:

Zitat von Schleifchen (Beitrag 1521975)
Hallo Thomas, ich bekomme mORMot nicht zum Laufen.

Lade dir mORMot2 Master herunter. Dann die Static-Binaries mORMot2Static.7z aus dem letzten Tag herunterladen. Entpacke den mORMot2 Master in dein gewünschtes Verzeichnis. Entpacke die Static-Binaries in das static Verzeichnis des mORMot2 Ordners. Dann die Bibliotheks- und Suchpfade in Delphi eintragen.

Bis bald...
Thomas

Schleifchen 3. Mai 2023 18:39

AW: Thingspeak - Datenabruf
 
Oh danke, das läuft jetzt.
Aber noch immer nicht fehlerfrei:
Code:
[dcc32 Fehler] Project1.dpr(58): E2003 Undeklarierter Bezeichner: 'TFileName'
[dcc32 Fehler] Project1.dpr(65): E2250 Es gibt keine überladene Version von 'Create', die man mit diesen Argumenten aufrufen kann
[dcc32 Fehler] Project1.dpr(74): E2003 Undeklarierter Bezeichner: 'IncYear'
[dcc32 Fehler] Project1.dpr(96): E2018 Record, Objekt oder Klassentyp erforderlich
[dcc32 Fehler] Project1.dpr(96): E2035 Nicht genügend wirkliche Parameter
[dcc32 Fehler] Project1.dpr(114): E2029 Deklaration erwartet, aber Dateiende gefunden
Misslungen
:cry:

mytbo 3. Mai 2023 18:45

AW: Thingspeak - Datenabruf
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Schleifchen (Beitrag 1521979)
Oh danke, das läuft jetzt.
Aber noch immer nicht fehlerfrei:

Hast du diese Delphi Units vergessen?
Delphi-Quellcode:
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.DateUtils,
Und auch Interface und Implementation Abschnitt schön getrennt.

Nachtrag: Habe besser gleich ein Beispiel Projekt (siehe Anhang) erstellt.

Bis bald...
Thomas

Schleifchen 3. Mai 2023 19:21

AW: Thingspeak - Datenabruf
 
Hallo Thomas, das läuft... perfekt und danke.

einen entspannte Abend noch - Stefan

mjustin 5. Mai 2023 17:18

AW: Thingspeak - Datenabruf
 
Dies sollte funktionieren - auch mit SSL (bis TLS 1.2):

Delphi-Quellcode:
  http := TIdHTTP.Create;
  try
    resultStr := http.Get( 'https://api.thingspeak.com/channels/9/fields/1.json?results=10' );
  finally
    http.Free;
  end;
Jedoch nur mit einer Indy-Version ab Ende 2014, Indy erzeugt dann den SSL-Handler, wenn das HTTPS Protokoll in der URL verwendet wird.

(Das ist für Testzwecke nützlich, da man weniger tippen muss. Hat man aber spezielle Anforderungen an die TLS-Konfiguration, geht es nur über den 'traditionellen' Weg)

https://www.indyproject.org/2014/12/...y-for-tidhttp/

Allerdings:

Zitat:

you still need to explicitly specify the desired SSLIOHandler unit in your uses clause


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz