Knowledge Base Nr: 00083 3964r.txt - http://www.swe-kaiser.de

Linux: Siemens R3964 Protokoll unter Linux und Oracle Forms verwenden
(Am Beispiel Heizzeitrechner der MIR in Oberwihl)

  

//////////////////c-interface/////////////////////////////////////////
c-header:
---------

extern "C"
{
int mir_hzr_open(const char* szDevice);

int mir_hzr_close();

const char* mir_hzr_send(const char* szRequest, int bWaitAndGetAnswer);

const char* mir_hzr_checkRequest();

const char* mir_hzr_lasterror();

const char* mir_hzr_lastsyserror();
}

cpp - implemtation:
-------------------

class CKRCom
{
public:
CKRCom();
~CKRCom();

int openCom(const char* lpszPort);
int closeCom();
...
protected:
bool checkForSysErrors(const char* lpszHint, ...);
...
private:
int m_hndPort;
...
};

int CKRCom::openCom(const char* lpszPort) //9600,n,8,1
{
...
#ifdef WIN32
...
m_hndPort = CreateFile( lpszPort,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
...
#else
...
m_hndPort = open(lpszPort, O_RDWR|O_NONBLOCK, 0);
...
#endif
...
}

c-wrapper:
----------

int kr_open(const char* szDevice)
{
...
g_pKR = new CKRCom();
...
int nErr = g_pKR->openCom(szDevice);
...
return nErr;
}

int kr_close()
{
...
int nErr = g_pKR->closeCom();
...
return nErr;
}


/******** MAKEFILE ************/

echo hzrlib bauen...
g++ -fPIC -g -c -Wall hzrlib.cpp
gcc -shared -Wl,-soname,libhzrlib.so.1 -o libhzrlib.so.1.0.1 hzrlib.o -lc
cp libhzrlib.so.1.0.1 /usr/lib/.
ldconfig

(evtl. noch alternativ visual studio project)

/******** FFIGEN ***********/
screenshot: ffigen.bmp

/******** PACKETSPEZIFIKATION ************/

PACKAGE mirhzrlib IS
FUNCTION mir_hzr_open(szDevice IN OUT VARCHAR2) RETURN PLS_INTEGER;
FUNCTION mir_hzr_close RETURN PLS_INTEGER;

FUNCTION mir_hzr_send(
szTelegramFromPC IN OUT VARCHAR2,
bWaitForAnswer IN OUT PLS_INTEGER
) RETURN VARCHAR2;

FUNCTION mir_hzr_checkRequest RETURN VARCHAR2;
FUNCTION mir_hzr_lasterror RETURN VARCHAR2;
FUNCTION mir_hzr_lastsyserror RETURN VARCHAR2;
END mirhzrlib;


/******** PACKAGE BODY *******************/

PACKAGE BODY mirhzrlib IS

-- Private Package Variables
lh_mirhzrlib ORA_FFI.LIBHANDLETYPE;
fh_mir_hzr_open ORA_FFI.FUNCHANDLETYPE;
fh_mir_hzr_close ORA_FFI.FUNCHANDLETYPE;
...

-- Private PU Declarations
PROCEDURE LoadLibrary;

FUNCTION i_mir_hzr_open(
FunctionHandle IN ORA_FFI.FUNCHANDLETYPE,
szDevice IN OUT VARCHAR2
) RETURN PLS_INTEGER;
PROCEDURE rg_mir_hzr_open;

FUNCTION i_mir_hzr_close(
FunctionHandle IN ORA_FFI.FUNCHANDLETYPE
) RETURN PLS_INTEGER;
PROCEDURE rg_mir_hzr_close;
...

-- Pragma statements which Hook the PL/SQL into the 3gl Function Call
-- *** Do Not Alter These Statements ***
PRAGMA INTERFACE(C,i_mir_hzr_open, 11265);
PRAGMA INTERFACE(C,i_mir_hzr_close, 11265);
...

-- Bodies for Private PUs
/*--------------------------------------------------------------*\
* The LoadLibrary procedure attempts to load the specified
* 3gl library file so the the functions within it can be
* accessed. It first of all checks to see if the Library
* file is loaded already, and if it isn't does the load.
\*--------------------------------------------------------------*/

PROCEDURE LoadLibrary IS
BEGIN
BEGIN
lh_mirhzrlib := ORA_FFI.LOAD_LIBRARY('/usr/lib/','libhzrlib.so.1.0.1');
-- WIndows NT 4.0: lh_mirhzrlib := ORA_FFI.FIND_LIBRARY('mirhzr.dll');
END;
EXCEPTION
WHEN OTHERS THEN
-- Place the first error on the TOOL_ERR stack into the package header variables available for it.
FFI_ERROR := TRUE;
FFI_Error_Text := TOOL_ERR.MESSAGE;
FFI_Error_Code := TOOL_ERR.CODE;
FOR iErrors IN 1..TOOL_ERR.NERRORS LOOP
Message('mirhzrlib: '||TOOL_ERR.MESSAGE);
TOOL_ERR.POP;
END LOOP;

TOOL_ERR.CLEAR;

END LoadLibrary;

PROCEDURE rg_mir_hzr_open IS
BEGIN
fh_mir_hzr_open := ORA_FFI.REGISTER_FUNCTION(lh_mirhzrlib,'mir_hzr_open',ORA_FFI.C_STD);
ORA_FFI.REGISTER_PARAMETER(fh_mir_hzr_open,ORA_FFI.C_CHAR_PTR);
ORA_FFI.REGISTER_RETURN(fh_mir_hzr_open,ORA_FFI.C_INT);
EXCEPTION
WHEN OTHERS THEN
-- Place the first error on the TOOL_ERR stack into the package header variables available for it.
FFI_ERROR := TRUE;
FFI_Error_Text := TOOL_ERR.MESSAGE;
FFI_Error_Code := TOOL_ERR.CODE;
FOR iErrors IN 1..TOOL_ERR.NERRORS LOOP
Message('mirhzrlib: '||TOOL_ERR.MESSAGE);
TOOL_ERR.POP;
END LOOP;

TOOL_ERR.CLEAR;

END rg_mir_hzr_open;
...

-- Bodies for Public PUs
FUNCTION mir_hzr_open(
szDevice IN OUT VARCHAR2
) RETURN PLS_INTEGER IS
RC PLS_INTEGER;
l_szDevice VARCHAR2(256) := RPAD(SUBSTR(NVL(szDevice,' '),1,256),256,CHR(0));
BEGIN

rc := i_mir_hzr_open(
fh_mir_hzr_open,
l_szDevice);
szDevice := l_szDevice;
RETURN RC;
END mir_hzr_open;

FUNCTION mir_hzr_close RETURN PLS_INTEGER IS
RC PLS_INTEGER;
BEGIN
...

BEGIN

LoadLibrary;
rg_mir_hzr_open;
rg_mir_hzr_close;
rg_mir_hzr_send;
rg_mir_hzr_checkRequest;
rg_mir_hzr_lasterror;
rg_mir_hzr_lastsyserror;
END mirhzrlib;

/******** TRIGGER WHEN-BUTTON-PRESSED *****************/

DECLARE
ret varchar(500) := null;
tele varchar(500) := null;
port varchar(500) := '/dev/ttyS0';
bWaitForAnswer PLS_INTEGER := 1;

BEGIN
--open
:CONTROL.ERROR := MIRHZRLIB.MIR_HZR_OPEN(port);
:CONTROL.ERRORTEXT := MIRHZRLIB.MIR_HZR_LASTERROR();
:CONTROL.SYSERRORTEXT := MIRHZRLIB.MIR_HZR_LASTSYSERROR();
synchronize;
if (:CONTROL.ERROR < 0) then
message('mir_hzr_open() gibt fehler zurück');
return;
end if;

--send
tele := '49:?' || chr(13) || chr(10);
ret := MIRHZRLIB.MIR_HZR_SEND(tele, bWaitForAnswer); --warten auf antwort
:CONTROL.HZRANSWER := ret;
:CONTROL.ERRORTEXT := MIRHZRLIB.MIR_HZR_LASTERROR();
:CONTROL.SYSERRORTEXT := MIRHZRLIB.MIR_HZR_LASTSYSERROR();
synchronize;
if (substr(ret,1,1) = '*') then
message('mir_hzr_send() gibt fehler zurück');
return;
end if;

--close
:CONTROL.ERROR := MIRHZRLIB.MIR_HZR_CLOSE();
:CONTROL.ERRORTEXT := MIRHZRLIB.MIR_HZR_LASTERROR();
:CONTROL.SYSERRORTEXT := MIRHZRLIB.MIR_HZR_LASTSYSERROR();
synchronize;
...
END;