Datenbankanbindung

Antworten
Barbers
Beiträge: 1
Registriert: Freitag 10. April 2009, 12:32

Datenbankanbindung

Beitrag von Barbers » Freitag 10. April 2009, 12:41

Hallo,

Ich wollte eine DLL schreiben die die eingehenden Messwerte in eine Datenbank schreibt.
Hier das ganze einmal mit SQLite.

Code: Alles auswählen

#include "dll.h"
#include <iostream>
#include <C:\Dokumente und Einstellungen\barbers\Desktop\sqlite-source\sqlite3.h> 
#include <ctime>
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include <stddef.h>
 //Anzahl der Eingaenge  
const unsigned char inputs = 17;  //17-Eingaenge
//Anzahl der Ausgaenge
const unsigned char outputs = 0; //0-Ausgaenge
//Eingang 0 = M01, Eingang 1 = M02 usw.
const unsigned char M01 = 0;
const unsigned char M02 = 1;
const unsigned char M03 = 2;
const unsigned char M04 = 3;
const unsigned char M05 = 4;
const unsigned char M06 = 5;
const unsigned char M07 = 6;
const unsigned char M08 = 7;
const unsigned char M09 = 8;
const unsigned char M10 = 9;
const unsigned char M11 = 10;
const unsigned char M12 = 11;
const unsigned char M13 = 12;
const unsigned char M14 = 13;
const unsigned char M15 = 14;
const unsigned char M16 = 15;
const unsigned char EXE = 16;
  
//Bezeichnung für User-variabelen
const unsigned char CLK_OLD = 0;
const unsigned char RST_OLD = 1;
const unsigned char COUNT = 2;
//
//Aufruf von PROFILAB, liest Anzahl der Eingänge 
DLLEXPORT unsigned char _stdcall NumInputs()
{
      return inputs;
}
  
//Aufruf von PROFILAB, liest Anzahl der Ausgaenge 
DLLEXPORT unsigned char _stdcall NumOutputs()
{
      return outputs;
}
  
//Aufruf von PROFILAB, liest die Namen der Eingänge 
DLLEXPORT void _stdcall GetInputName(unsigned char Channel,unsigned char *Name)
{
			switch(Channel)
			{	

case 0://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '1';
			Name[3]=0;
			break;
	  }

case 1://Bezeichnung Eingang-1
	  {
			Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '2';
			Name[3]= 0;
			break;
	  }
case 2://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '3';
			Name[3]=0;
			break;
	  }
case 3://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '4';
			Name[3]=0;
			break;
	  }
case 4://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '5';
			Name[3]=0;
			break;
	  }
case 5://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '6';
			Name[3]=0;
			break;
	  }
case 6://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '7';
			Name[3]=0;
			break;
	  }
case 7://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '8';
			Name[3]=0;
			break;
	  }
case 8://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '0';
			Name[2]= '9';
			Name[3]=0;
			break;
	  }
case 9://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '0';
			Name[3]=0;
			break;
	  }
case 10://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '1';
			Name[3]=0;
			break;
	  }
case 11://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '2';
			Name[3]=0;
			break;
	  }
case 12://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '3';
			Name[3]=0;
			break;
	  }
case 13://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '4';
			Name[3]=0;
			break;
	  }
case 14://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '5';
			Name[3]=0;
			break;
	  }
case 15://Bezeichnung Eingang-0
		  {
            Name[0]= 'M';
			Name[1]= '1';
			Name[2]= '6';
			Name[3]=0;
			break;
	  }
case 16://Bezeichnung Eingang-0
		  {
            Name[0]= 'E';
			Name[1]= 'X';
			Name[2]= 'E';
			Name[3]=0;
			break;
	  }
	default:;
   }
}
  
//Aufruf von PROFILAB, liest die Namen der Eingänge 
DLLEXPORT void _stdcall GetOutputName(unsigned char Channel,unsigned char *Name)
{
			switch(Channel)
			{
	
	default:;
			}

}
  
//Aufruf von PROFILAB, setzt bei Programmstart den "Counter"auf "0"+ setzt alle Ausgaenge zurueck
DLLEXPORT void _stdcall CSimStart(double *PInput, double *POutput, double *PUser)
{
      int i;
  
      PUser[COUNT] = 0;               //"Counter" ruecksetzen
      for (i = 0; i < outputs; i++)   //Alle Ausgaenge ruecksetzen
                POutput[i] = 0;
}
  
//Aufruf von PROFILAB,hier steht die eigentliche Funktion der DLL
//
DLLEXPORT void _stdcall CCalculate(double *PInput, double *POutput, double *PUser)
{
      int i, iCount;
      char messwerte[400];

      if (PInput[EXE] != 0) // EXE Eingang high?
      {
   sqlite3* datenbank;
    if(sqlite3_open("C:\Dokumente und Einstellungen\barbers\Desktop\dll_dev_c++\Counter_DLL_Dev_C++\current.db", &datenbank) != SQLITE_OK)
   {
   }

     sprintf( messwerte, "insert into messwerte (number, m01 , m02, m03, m04, m05, m06, m07, m08, m09, m10, m11, m12, m13, m14 ,m15 ,m16) VALUES ((SELECT max(number) FROM messwerte)+1, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d ,%d ,%d, %d);", PInput[M01], PInput[M02], PInput[M03], PInput[M04], PInput[M05], PInput[M06], PInput[M07], PInput[M08], PInput[M09], PInput[M10], PInput[M11], PInput[M12], PInput[M13], PInput[M14], PInput[M15], PInput[M16] );


   sqlite3_exec( datenbank , messwerte , NULL , NULL , NULL);
   sqlite3_close(datenbank);
      }
}
  
// Aufruf von PROFILAB, wird beim Simulations-Stop aufgerufen
DLLEXPORT void _stdcall CSimStop(double *PInput, double *POutput, double *PUser)
{
//nichts zu tun
}
// erforderlich für MessageBox
int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szComdLine, int iCmdShow);  
//Aufruf von PROFILAB, wird im Configurations-Menü aufgerufen

DLLEXPORT void _stdcall CConfigure(double *PUser)
{
MessageBox(NULL,TEXT("nichts zu configurieren"),TEXT("Config"), MB_OK);
}





BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        break;

      case DLL_PROCESS_DETACH:
        break;

      case DLL_THREAD_ATTACH:
        break;

      case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}
Vielleicht findet jemand den Fehler warum nichts in die Datenbank geschrieben wird.

Lg Barbers

KAKTUS
Beiträge: 651
Registriert: Samstag 18. Oktober 2008, 21:12

Re: Datenbankanbindung

Beitrag von KAKTUS » Freitag 10. April 2009, 15:44

Ja das ist ja mal wieder ein interessanter Beitrag.

Ich kann dir leider bei deinem Problem nicht helfen, ich kann nur versprechen deine Beiträge mit Adlerauge zu beobachten. Finde es toll das dem Thema Datenbank sich jemand annimmt. Bin besonders interessiert an schreiben und lesen in MySQL Datenbank.
stachlige Grüße, Kaktus

abacom
Site Admin
Beiträge: 3917
Registriert: Dienstag 23. September 2008, 10:54
Kontaktdaten:

Re: Datenbankanbindung

Beitrag von abacom » Freitag 10. April 2009, 22:01

Wenn ich den C-Code richtig lese steht darin ungefähr:

Wenn (solange) EXE Pin high ist, dann
- Öffne Datenbank
- Schreibe in Datenbank
- Schliesse Datenbank sofort wieder

Man beachte, dass diese Abfolge von ProfiLab ständig und immer wieder aufgerufen wird! Evtl. mehrere 1000 mal pro Sekunde!

Besser wäre wohl...

- Bei SimStart -> Öffne Datenbank

- Bei (z.B. fallender) FLANKE (nicht Pegel) am EXE-Pin -> Schreibe Datensatz (Append)

- Bei SimStop -> Schliesse Datenbank

Das Öffnen und Schliessen liesse sich ggf. von einem weiteren Pin abhängig machen, wenn man SimStart und SimStop dafür nicht verwenden möchte.

Ob das das Problem löst weiss ich nicht, aber ich würde diesen Ansatz dringend anraten. Die Datenbank-Befehle kenne ich leider nicht.
ABACOM support

ExpertProfi
Beiträge: 43
Registriert: Freitag 30. Januar 2009, 11:36

Re: Datenbankanbindung

Beitrag von ExpertProfi » Freitag 10. April 2009, 22:20

Ist zwar Delphi, aber vielleicht hilft´s:

Code: Alles auswählen

Procedure Calculate(PInput,POutput,PUser: PDLLParams); //called regularly from ProfiLab
var R,W, R_old, W_old: Boolean;
    IniFile: TIniFile;

   procedure ReadData; //Read output values from file
   var i: Integer;
   begin
      IniFile:=TIniFile.Create(ExtractFilePath(Application.Exename)+'Data\Permanent_Memory'+intToStr(round(PUser^[100]))+'.ini');
      For i:=0 to 15 do POutput^[i]:=IniFile.ReadFloat('Permanent','Memory'+intToStr(i),0);
      IniFile.Free;
   end;

   procedure WriteData; //Write input values to file
   var i: Integer;
   begin
      IniFile:=TIniFile.Create(ExtractFilePath(Application.Exename)+'Data\Permanent_Memory'+intToStr(round(PUser^[100]))+'.ini');
      For i:=0 to 15 do IniFile.WriteFloat('Permanent','Memory'+intToStr(i),PInput^[i]);
      IniFile.Free;
   end;

begin
   R:=PInput^[RD]>2.5;
   W:=PInput^[WR]>2.5;
   R_old:=PUser^[RD_old]>2.5;
   W_old:=PUser^[WR_old]>2.5;

   if (not R) and R_old then ReadData; //falling edge of RD
   if (not W) and W_old then WriteData; //falling edge of WR
   
   PUser^[RD_old]:=PInput^[RD];
   PUser^[WR_old]:=PInput^[WR];
end;
Da hättest Du zumindest schon einmal ein Gerüst für die Flankensteuerung, die abacom meint. Die Source stammt aus meiner Permanent_Memory DLL.

http://www.expertprofi.ag.vu/permanent_mem.html

Willst Du eigentlich nur EINEN Datensatz mit den letzten Werten in der DB haben, oder fortlaufend in eine Tabelle loggen?

Antworten

Zurück zu „Datenschnittstellen“