Merge pull request #267 from davenardella/master

S7 Protocol implementation
This commit is contained in:
Thiago Alves
2025-03-17 14:58:38 -04:00
committed by GitHub
48 changed files with 19333 additions and 20 deletions
+9
View File
@@ -212,6 +212,14 @@ function install_libmodbus {
fi
}
function install_libsnap7 {
echo "[LIBSNAP7]"
cd "$OPENPLC_DIR/utils/snap7_src/build/linux"
$1 make clean
$1 make install || fail "Error installing Libsnap7"
cd "$OPENPLC_DIR"
}
function install_systemd_service() {
if [ "$1" == "sudo" ]; then
echo "[OPENPLC SERVICE]"
@@ -245,6 +253,7 @@ function install_all_libs {
install_opendnp3 "$1"
disable_ethercat "$1"
install_libmodbus "$1"
install_libsnap7 "$1"
}
function finalize_install {
@@ -0,0 +1 @@
This folder is empty, it will contain the linux library after the build
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+111
View File
@@ -0,0 +1,111 @@
#
# Common for every unix flavour (any changes will be reflected on all platforms)
#
CXXFLAGS := -O3 -fPIC -pedantic
ConfigurationName :=Release
IntermediateDirectory :=../temp
OutDir := $(IntermediateDirectory)
LinkerName :=g++
SharedObjectLinkerName :=g++ -shared -fPIC
DebugSwitch :=-gstab
IncludeSwitch :=-I
LibrarySwitch :=-l
OutputSwitch :=-o
LibraryPathSwitch :=-L
PreprocessorSwitch :=-D
SourceSwitch :=-c
OutputFile :=../bin/linux/libsnap7.so
PreprocessOnlySwitch :=-E
ObjectsFileList :="filelist.txt"
MakeDirCommand :=mkdir -p
LinkOptions := -O3
IncludePath := $(IncludeSwitch). $(IncludeSwitch)../../src/sys $(IncludeSwitch)../../src/core $(IncludeSwitch)../../src/lib
Libs := $(LibrarySwitch)pthread $(LibrarySwitch)rt
LibPath := $(LibraryPathSwitch).
LibInstall := /usr/lib
##
## Common variables (CXXFLAGS varies across platforms)
##
AR := ar rcus
CXX := g++
CC := gcc
CFLAGS :=
##
## User defined environment variables
##
Objects0=$(IntermediateDirectory)/sys_snap_msgsock.o $(IntermediateDirectory)/sys_snap_sysutils.o $(IntermediateDirectory)/sys_snap_tcpsrvr.o $(IntermediateDirectory)/sys_snap_threads.o $(IntermediateDirectory)/core_s7_client.o $(IntermediateDirectory)/core_s7_isotcp.o $(IntermediateDirectory)/core_s7_partner.o $(IntermediateDirectory)/core_s7_peer.o $(IntermediateDirectory)/core_s7_server.o $(IntermediateDirectory)/core_s7_text.o \
$(IntermediateDirectory)/core_s7_micro_client.o $(IntermediateDirectory)/lib_snap7_libmain.o
Objects=$(Objects0)
##
## Main Build Targets
##
.PHONY: all clean install PreBuild PostBuild
all: $(OutputFile)
$(OutputFile): $(IntermediateDirectory)/.d $(Objects)
@$(MakeDirCommand) $(@D)
@$(MakeDirCommand) $(IntermediateDirectory)
@echo $(Objects0) > $(ObjectsFileList)
$(SharedObjectLinkerName) $(OutputSwitch)$(OutputFile) @$(ObjectsFileList) $(LibPath) $(Libs) $(LinkOptions)
$(RM) $(ObjectsFileList)
$(IntermediateDirectory)/.d:
@test -d ../temp || $(MakeDirCommand) ../temp
PreBuild:
PostBuild:
##
## Objects
##
$(IntermediateDirectory)/sys_snap_msgsock.o:
$(CXX) $(SourceSwitch) "../../src/sys/snap_msgsock.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/sys_snap_msgsock.o $(IncludePath)
$(IntermediateDirectory)/sys_snap_sysutils.o:
$(CXX) $(SourceSwitch) "../../src/sys/snap_sysutils.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/sys_snap_sysutils.o $(IncludePath)
$(IntermediateDirectory)/sys_snap_tcpsrvr.o:
$(CXX) $(SourceSwitch) "../../src/sys/snap_tcpsrvr.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/sys_snap_tcpsrvr.o $(IncludePath)
$(IntermediateDirectory)/sys_snap_threads.o:
$(CXX) $(SourceSwitch) "../../src/sys/snap_threads.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/sys_snap_threads.o $(IncludePath)
$(IntermediateDirectory)/core_s7_client.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_client.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_client.o $(IncludePath)
$(IntermediateDirectory)/core_s7_isotcp.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_isotcp.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_isotcp.o $(IncludePath)
$(IntermediateDirectory)/core_s7_partner.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_partner.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_partner.o $(IncludePath)
$(IntermediateDirectory)/core_s7_peer.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_peer.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_peer.o $(IncludePath)
$(IntermediateDirectory)/core_s7_server.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_server.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_server.o $(IncludePath)
$(IntermediateDirectory)/core_s7_text.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_text.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_text.o $(IncludePath)
$(IntermediateDirectory)/core_s7_micro_client.o:
$(CXX) $(SourceSwitch) "../../src/core/s7_micro_client.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/core_s7_micro_client.o $(IncludePath)
$(IntermediateDirectory)/lib_snap7_libmain.o:
$(CXX) $(SourceSwitch) "../../src/lib/snap7_libmain.cpp" $(CXXFLAGS) -o $(IntermediateDirectory)/lib_snap7_libmain.o $(IncludePath)
##
## Clean / Install
##
clean:
$(RM) $(IntermediateDirectory)/*.o
$(RM) $(OutputFile)
install: all
cp -f $(OutputFile) $(LibInstall)
+1
View File
@@ -0,0 +1 @@
This folder is empty, will contain intermediate files after the installation (you can delete the content)
+3
View File
@@ -0,0 +1,3 @@
There is no Windows installation makefile.
Instead, DLLs build witn Visual Studio 2022 are used, because they are smaller and faster.
Anyway, if you want, the Snap7 distribution contains the makefiles to build the library using mingw(32/64).
+1
View File
@@ -0,0 +1 @@
This folder contains S7 Protocol implementation sources
File diff suppressed because it is too large Load Diff
+104
View File
@@ -0,0 +1,104 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_client_h
#define s7_client_h
//---------------------------------------------------------------------------
#include "snap_threads.h"
#include "s7_micro_client.h"
//---------------------------------------------------------------------------
extern "C" {
typedef void (S7API *pfn_CliCompletion) (void * usrPtr, int opCode, int opResult);
}
class TSnap7Client;
class TClientThread: public TSnapThread
{
private:
TSnap7Client * FClient;
public:
TClientThread(TSnap7Client *Client)
{
FClient = Client;
}
void Execute();
};
//---------------------------------------------------------------------------
class TSnap7Client: public TSnap7MicroClient
{
private:
TClientThread *FThread;
bool ThreadCreated;
void CloseThread();
void OpenThread();
void StartAsyncJob();
protected:
PSnapEvent EvtJob;
PSnapEvent EvtComplete;
pfn_CliCompletion CliCompletion;
void *FUsrPtr;
void DoCompletion();
public:
friend class TClientThread;
TSnap7Client();
~TSnap7Client();
int Reset(bool DoReconnect);
int SetAsCallback(pfn_CliCompletion pCompletion, void * usrPtr);
int GetParam(int ParamNumber, void *pValue);
int SetParam(int ParamNumber, void *pValue);
// Async functions
bool CheckAsCompletion( int & opResult);
int WaitAsCompletion(unsigned long Timeout);
int AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData);
int AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData);
int AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int & ItemsCount);
int AsReadSZL(int ID, int Index, PS7SZL pUsrData, int & Size);
int AsReadSZLList(PS7SZLList pUsrData, int &ItemsCount);
int AsUpload(int BlockType, int BlockNum, void * pUsrData, int & Size);
int AsFullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size);
int AsDownload(int BlockNum, void * pUsrData, int Size);
int AsCopyRamToRom(int Timeout);
int AsCompress(int Timeout);
int AsDBRead(int DBNumber, int Start, int Size, void * pUsrData);
int AsDBWrite(int DBNumber, int Start, int Size, void * pUsrData);
int AsMBRead(int Start, int Size, void * pUsrData);
int AsMBWrite(int Start, int Size, void * pUsrData);
int AsEBRead(int Start, int Size, void * pUsrData);
int AsEBWrite(int Start, int Size, void * pUsrData);
int AsABRead(int Start, int Size, void * pUsrData);
int AsABWrite(int Start, int Size, void * pUsrData);
int AsTMRead(int Start, int Amount, void * pUsrData);
int AsTMWrite(int Start, int Amount, void * pUsrData);
int AsCTRead(int Start, int Amount, void * pUsrData);
int AsCTWrite(int Start, int Amount, void * pUsrData);
int AsDBGet(int DBNumber, void * pUsrData, int & Size);
int AsDBFill(int DBNumber, int FillChar);
};
typedef TSnap7Client *PSnap7Client;
//---------------------------------------------------------------------------
#endif // s7_client_h
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+271
View File
@@ -0,0 +1,271 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_isotcp_h
#define s7_isotcp_h
//---------------------------------------------------------------------------
#include "snap_msgsock.h"
//---------------------------------------------------------------------------
#pragma pack(1)
#define isoTcpVersion 3 // RFC 1006
#define isoTcpPort 102 // RFC 1006
#define isoInvalidHandle 0
#define MaxTSAPLength 16 // Max Lenght for Src and Dst TSAP
#define MaxIsoFragments 64 // Max fragments
#define IsoPayload_Size 4096 // Iso telegram Buffer size
#define noError 0
const longword errIsoMask = 0x000F0000;
const longword errIsoBase = 0x0000FFFF;
const longword errIsoConnect = 0x00010000; // Connection error
const longword errIsoDisconnect = 0x00020000; // Disconnect error
const longword errIsoInvalidPDU = 0x00030000; // Bad format
const longword errIsoInvalidDataSize = 0x00040000; // Bad Datasize passed to send/recv : buffer is invalid
const longword errIsoNullPointer = 0x00050000; // Null passed as pointer
const longword errIsoShortPacket = 0x00060000; // A short packet received
const longword errIsoTooManyFragments = 0x00070000; // Too many packets without EoT flag
const longword errIsoPduOverflow = 0x00080000; // The sum of fragments data exceded maximum packet size
const longword errIsoSendPacket = 0x00090000; // An error occurred during send
const longword errIsoRecvPacket = 0x000A0000; // An error occurred during recv
const longword errIsoInvalidParams = 0x000B0000; // Invalid TSAP params
const longword errIsoResvd_1 = 0x000C0000; // Unassigned
const longword errIsoResvd_2 = 0x000D0000; // Unassigned
const longword errIsoResvd_3 = 0x000E0000; // Unassigned
const longword errIsoResvd_4 = 0x000F0000; // Unassigned
const longword ISO_OPT_TCP_NODELAY = 0x00000001; // Disable Nagle algorithm
const longword ISO_OPT_INSIDE_MTU = 0x00000002; // Max packet size < MTU ethernet card
// TPKT Header - ISO on TCP - RFC 1006 (4 bytes)
typedef struct{
u_char Version; // Always 3 for RFC 1006
u_char Reserved; // 0
u_char HI_Lenght; // High part of packet lenght (entire frame, payload and TPDU included)
u_char LO_Lenght; // Low part of packet lenght (entire frame, payload and TPDU included)
} TTPKT; // Packet length : min 7 max 65535
typedef struct {
u_char PduSizeCode;
u_char PduSizeLen;
u_char PduSizeVal;
u_char TSAP[245]; // We don't know in advance these fields....
} TCOPT_Params ;
// PDU Type constants - ISO 8073, not all are mentioned in RFC 1006
// For our purposes we use only those labeled with **
// These constants contains 4 low bit order 0 (credit nibble)
//
// $10 ED : Expedited Data
// $20 EA : Expedited Data Ack
// $40 UD : CLTP UD
// $50 RJ : Reject
// $70 AK : Ack data
// ** $80 DR : Disconnect request (note : S7 doesn't use it)
// ** $C0 DC : Disconnect confirm (note : S7 doesn't use it)
// ** $D0 CC : Connection confirm
// ** $E0 CR : Connection request
// ** $F0 DT : Data
//
// COTP Header for CONNECTION REQUEST/CONFIRM - DISCONNECT REQUEST/CONFIRM
typedef struct {
u_char HLength; // Header length : initialized to 6 (length without params - 1)
// descending classes that add values in params field must update it.
u_char PDUType; // 0xE0 Connection request
// 0xD0 Connection confirm
// 0x80 Disconnect request
// 0xDC Disconnect confirm
u_short DstRef; // Destination reference : Always 0x0000
u_short SrcRef; // Source reference : Always 0x0000
u_char CO_R; // If the telegram is used for Connection request/Confirm,
// the meaning of this field is CLASS+OPTION :
// Class (High 4 bits) + Option (Low 4 bits)
// Class : Always 4 (0100) but is ignored in input (RFC States this)
// Option : Always 0, also this in ignored.
// If the telegram is used for Disconnect request,
// the meaning of this field is REASON :
// 1 Congestion at TSAP
// 2 Session entity not attached to TSAP
// 3 Address unknown (at TCP connect time)
// 128+0 Normal disconnect initiated by the session
// entity.
// 128+1 Remote transport entity congestion at connect
// request time
// 128+3 Connection negotiation failed
// 128+5 Protocol Error
// 128+8 Connection request refused on this network
// connection
// Parameter data : depending on the protocol implementation.
// ISO 8073 define several type of parameters, but RFC 1006 recognizes only
// TSAP related parameters and PDU size. See RFC 0983 for more details.
TCOPT_Params Params;
/* Other params not used here, list only for completeness
ACK_TIME = 0x85, 1000 0101 Acknowledge Time
RES_ERROR = 0x86, 1000 0110 Residual Error Rate
PRIORITY = 0x87, 1000 0111 Priority
TRANSIT_DEL = 0x88, 1000 1000 Transit Delay
THROUGHPUT = 0x89, 1000 1001 Throughput
SEQ_NR = 0x8A, 1000 1010 Subsequence Number (in AK)
REASSIGNMENT = 0x8B, 1000 1011 Reassignment Time
FLOW_CNTL = 0x8C, 1000 1100 Flow Control Confirmation (in AK)
TPDU_SIZE = 0xC0, 1100 0000 TPDU Size
SRC_TSAP = 0xC1, 1100 0001 TSAP-ID / calling TSAP ( in CR/CC )
DST_TSAP = 0xC2, 1100 0010 TSAP-ID / called TSAP
CHECKSUM = 0xC3, 1100 0011 Checksum
VERSION_NR = 0xC4, 1100 0100 Version Number
PROTECTION = 0xC5, 1100 0101 Protection Parameters (user defined)
OPT_SEL = 0xC6, 1100 0110 Additional Option Selection
PROTO_CLASS = 0xC7, 1100 0111 Alternative Protocol Classes
PREF_MAX_TPDU_SIZE = 0xF0, 1111 0000
INACTIVITY_TIMER = 0xF2, 1111 0010
ADDICC = 0xe0 1110 0000 Additional Information on Connection Clearing
*/
} TCOTP_CO ;
typedef TCOTP_CO *PCOTP_CO;
// COTP Header for DATA EXCHANGE
typedef struct {
u_char HLength; // Header length : 3 for this header
u_char PDUType; // 0xF0 for this header
u_char EoT_Num; // EOT (bit 7) + PDU Number (bits 0..6)
// EOT = 1 -> End of Trasmission Packet (This packet is complete)
// PDU Number : Always 0
} TCOTP_DT;
typedef TCOTP_DT *PCOTP_DT;
// Info part of a PDU, only common parts. We use it to check the consistence
// of a telegram regardless of it's nature (control or data).
typedef struct {
TTPKT TPKT; // TPKT Header
// Common part of any COTP
u_char HLength; // Header length : 3 for this header
u_char PDUType; // Pdu type
} TIsoHeaderInfo ;
typedef TIsoHeaderInfo *PIsoHeaderInfo;
// PDU Type consts (Code + Credit)
const byte pdu_type_CR = 0xE0; // Connection request
const byte pdu_type_CC = 0xD0; // Connection confirm
const byte pdu_type_DR = 0x80; // Disconnect request
const byte pdu_type_DC = 0xC0; // Disconnect confirm
const byte pdu_type_DT = 0xF0; // Data transfer
const byte pdu_EoT = 0x80; // End of Trasmission Packet (This packet is complete)
const longword DataHeaderSize = sizeof(TTPKT)+sizeof(TCOTP_DT);
const longword IsoFrameSize = IsoPayload_Size+DataHeaderSize;
typedef struct {
TTPKT TPKT; // TPKT Header
TCOTP_CO COTP; // COPT Header for CONNECTION stuffs
} TIsoControlPDU;
typedef TIsoControlPDU *PIsoControlPDU;
typedef u_char TIsoPayload[IsoPayload_Size];
typedef struct {
TTPKT TPKT; // TPKT Header
TCOTP_DT COTP; // COPT Header for DATA EXCHANGE
TIsoPayload Payload; // Payload
} TIsoDataPDU ;
typedef TIsoDataPDU *PIsoDataPDU;
typedef TIsoPayload *PIsoPayload;
typedef enum {
pkConnectionRequest,
pkDisconnectRequest,
pkEmptyFragment,
pkInvalidPDU,
pkUnrecognizedType,
pkValidData
} TPDUKind ;
#pragma pack()
void ErrIsoText(int Error, char *Msg, int len);
class TIsoTcpSocket : public TMsgSocket
{
private:
TIsoControlPDU FControlPDU;
int IsoMaxFragments; // max fragments allowed for an ISO telegram
// Checks the PDU format
int CheckPDU(void *pPDU, u_char PduTypeExpected);
// Receives the next fragment
int isoRecvFragment(void *From, int Max, int &Size, bool &EoT);
protected:
TIsoDataPDU PDU;
int SetIsoError(int Error);
// Builds the control PDU starting from address properties
virtual int BuildControlPDU();
// Calcs the PDU size
int PDUSize(void *pPDU);
// Parses the connection request PDU to extract TSAP and PDU size info
virtual void IsoParsePDU(TIsoControlPDU PDU);
// Confirms the connection, override this method for special pourpose
// By default it checks the PDU format and resend it changing the pdu type
int IsoConfirmConnection(u_char PDUType);
void ClrIsoError();
virtual void FragmentSkipped(int Size);
public:
word SrcTSap; // Source TSAP
word DstTSap; // Destination TSAP
word SrcRef; // Source Reference
word DstRef; // Destination Reference
int IsoPDUSize;
int LastIsoError;
//--------------------------------------------------------------------------
TIsoTcpSocket();
~TIsoTcpSocket();
// HIGH Level functions (work on payload hiding the underlying protocol)
// Connects with a peer, the connection PDU is automatically built starting from address scheme (see below)
int isoConnect();
// Disconnects from a peer, if OnlyTCP = true, only a TCP disconnect is performed,
// otherwise a disconnect PDU is built and send.
int isoDisconnect(bool OnlyTCP);
// Sends a buffer, a valid header is created
int isoSendBuffer(void *Data, int Size);
// Receives a buffer
int isoRecvBuffer(void *Data, int & Size);
// Exchange cycle send->receive
int isoExchangeBuffer(void *Data, int & Size);
// A PDU is ready (at least its header) to be read
bool IsoPDUReady();
// Same as isoSendBuffer, but the entire PDU has to be provided (in any case a check is performed)
int isoSendPDU(PIsoDataPDU Data);
// Same as isoRecvBuffer, but it returns the entire PDU, automatically enques the fragments
int isoRecvPDU(PIsoDataPDU Data);
// Same as isoExchangeBuffer, but the entire PDU has to be provided (in any case a check is performed)
int isoExchangePDU(PIsoDataPDU Data);
// Peeks an header info to know which kind of telegram is incoming
void IsoPeek(void *pPDU, TPDUKind &PduKind);
};
#endif // s7_isotcp_h
File diff suppressed because it is too large Load Diff
+364
View File
@@ -0,0 +1,364 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_micro_client_h
#define s7_micro_client_h
//---------------------------------------------------------------------------
#include "s7_peer.h"
//---------------------------------------------------------------------------
const longword errCliMask = 0xFFF00000;
const longword errCliBase = 0x000FFFFF;
const longword errCliInvalidParams = 0x00200000;
const longword errCliJobPending = 0x00300000;
const longword errCliTooManyItems = 0x00400000;
const longword errCliInvalidWordLen = 0x00500000;
const longword errCliPartialDataWritten = 0x00600000;
const longword errCliSizeOverPDU = 0x00700000;
const longword errCliInvalidPlcAnswer = 0x00800000;
const longword errCliAddressOutOfRange = 0x00900000;
const longword errCliInvalidTransportSize = 0x00A00000;
const longword errCliWriteDataSizeMismatch = 0x00B00000;
const longword errCliItemNotAvailable = 0x00C00000;
const longword errCliInvalidValue = 0x00D00000;
const longword errCliCannotStartPLC = 0x00E00000;
const longword errCliAlreadyRun = 0x00F00000;
const longword errCliCannotStopPLC = 0x01000000;
const longword errCliCannotCopyRamToRom = 0x01100000;
const longword errCliCannotCompress = 0x01200000;
const longword errCliAlreadyStop = 0x01300000;
const longword errCliFunNotAvailable = 0x01400000;
const longword errCliUploadSequenceFailed = 0x01500000;
const longword errCliInvalidDataSizeRecvd = 0x01600000;
const longword errCliInvalidBlockType = 0x01700000;
const longword errCliInvalidBlockNumber = 0x01800000;
const longword errCliInvalidBlockSize = 0x01900000;
const longword errCliDownloadSequenceFailed = 0x01A00000;
const longword errCliInsertRefused = 0x01B00000;
const longword errCliDeleteRefused = 0x01C00000;
const longword errCliNeedPassword = 0x01D00000;
const longword errCliInvalidPassword = 0x01E00000;
const longword errCliNoPasswordToSetOrClear = 0x01F00000;
const longword errCliJobTimeout = 0x02000000;
const longword errCliPartialDataRead = 0x02100000;
const longword errCliBufferTooSmall = 0x02200000;
const longword errCliFunctionRefused = 0x02300000;
const longword errCliDestroying = 0x02400000;
const longword errCliInvalidParamNumber = 0x02500000;
const longword errCliCannotChangeParam = 0x02600000;
const time_t DeltaSecs = 441763200; // Seconds between 1970/1/1 (C time base) and 1984/1/1 (Siemens base)
#pragma pack(1)
// Read/Write Multivars
typedef struct{
int Area;
int WordLen;
int Result;
int DBNumber;
int Start;
int Amount;
void *pdata;
} TS7DataItem, *PS7DataItem;
typedef int TS7ResultItems[MaxVars];
typedef TS7ResultItems *PS7ResultItems;
typedef struct {
int OBCount;
int FBCount;
int FCCount;
int SFBCount;
int SFCCount;
int DBCount;
int SDBCount;
} TS7BlocksList, *PS7BlocksList;
typedef struct {
int BlkType;
int BlkNumber;
int BlkLang;
int BlkFlags;
int MC7Size; // The real size in bytes
int LoadSize;
int LocalData;
int SBBLength;
int CheckSum;
int Version;
// Chars info
char CodeDate[11];
char IntfDate[11];
char Author[9];
char Family[9];
char Header[9];
} TS7BlockInfo, *PS7BlockInfo ;
typedef word TS7BlocksOfType[0x2000];
typedef TS7BlocksOfType *PS7BlocksOfType;
typedef struct {
char Code[21]; // Order Code
byte V1; // Version V1.V2.V3
byte V2;
byte V3;
} TS7OrderCode, *PS7OrderCode;
typedef struct {
char ModuleTypeName[33];
char SerialNumber[25];
char ASName[25];
char Copyright[27];
char ModuleName[25];
} TS7CpuInfo, *PS7CpuInfo;
typedef struct {
int MaxPduLengt;
int MaxConnections;
int MaxMpiRate;
int MaxBusRate;
} TS7CpInfo, *PS7CpInfo;
// See §33.1 of "System Software for S7-300/400 System and Standard Functions"
// and see SFC51 description too
typedef struct {
word LENTHDR;
word N_DR;
} SZL_HEADER, *PSZL_HEADER;
typedef struct {
SZL_HEADER Header;
byte Data[0x4000-4];
} TS7SZL, *PS7SZL;
// SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted
typedef struct {
SZL_HEADER Header;
word List[0x2000-2];
} TS7SZLList, *PS7SZLList;
// See §33.19 of "System Software for S7-300/400 System and Standard Functions"
typedef struct {
word sch_schal;
word sch_par;
word sch_rel;
word bart_sch;
word anl_sch;
} TS7Protection, *PS7Protection;
#define s7opNone 0
#define s7opReadArea 1
#define s7opWriteArea 2
#define s7opReadMultiVars 3
#define s7opWriteMultiVars 4
#define s7opDBGet 5
#define s7opUpload 6
#define s7opDownload 7
#define s7opDelete 8
#define s7opListBlocks 9
#define s7opAgBlockInfo 10
#define s7opListBlocksOfType 11
#define s7opReadSzlList 12
#define s7opReadSZL 13
#define s7opGetDateTime 14
#define s7opSetDateTime 15
#define s7opGetOrderCode 16
#define s7opGetCpuInfo 17
#define s7opGetCpInfo 18
#define s7opGetPlcStatus 19
#define s7opPlcHotStart 20
#define s7opPlcColdStart 21
#define s7opCopyRamToRom 22
#define s7opCompress 23
#define s7opPlcStop 24
#define s7opGetProtection 25
#define s7opSetPassword 26
#define s7opClearPassword 27
#define s7opDBFill 28
// Param Number (to use with setparam)
// Low level : change them to experiment new connections, their defaults normally work well
const int pc_iso_SendTimeout = 6;
const int pc_iso_RecvTimeout = 7;
const int pc_iso_ConnTimeout = 8;
const int pc_iso_SrcRef = 1;
const int pc_iso_DstRef = 2;
const int pc_iso_SrcTSAP = 3;
const int pc_iso_DstTSAP = 4;
const int pc_iso_IsoPduSize = 5;
// Client Connection Type
const word CONNTYPE_PG = 0x01; // Connect to the PLC as a PG
const word CONNTYPE_OP = 0x02; // Connect to the PLC as an OP
const word CONNTYPE_BASIC = 0x03; // Basic connection
#pragma pack()
// Internal struct for operations
// Commands are not executed directly in the function such as "DBRead(...",
// but this struct is filled and then PerformOperation() is called.
// This allow us to implement async function very easily.
struct TSnap7Job
{
int Op; // Operation Code
int Result; // Operation result
bool Pending; // A Job is pending
longword Time; // Job Execution time
// Read/Write
int Area; // Also used for Block type and Block of type
int Number; // Used for DB Number, Block number
int Start; // Offset start
int WordLen; // Word length
// SZL
int ID; // SZL ID
int Index; // SZL Index
// ptr info
void * pData; // User data pointer
int Amount; // Items amount/Size in input
int *pAmount; // Items amount/Size in output
// Generic
int IParam; // Used for full upload and CopyRamToRom extended timeout
};
class TSnap7MicroClient: public TSnap7Peer
{
private:
void FillTime(word SiemensTime, char *PTime);
byte BCDtoByte(byte B);
byte WordToBCD(word Value);
int opReadArea();
int opWriteArea();
int opReadMultiVars();
int opWriteMultiVars();
int opListBlocks();
int opListBlocksOfType();
int opAgBlockInfo();
int opDBGet();
int opDBFill();
int opUpload();
int opDownload();
int opDelete();
int opReadSZL();
int opReadSZLList();
int opGetDateTime();
int opSetDateTime();
int opGetOrderCode();
int opGetCpuInfo();
int opGetCpInfo();
int opGetPlcStatus();
int opPlcStop();
int opPlcHotStart();
int opPlcColdStart();
int opCopyRamToRom();
int opCompress();
int opGetProtection();
int opSetPassword();
int opClearPassword();
int CpuError(int Error);
longword DWordAt(void * P);
int CheckBlock(int BlockType, int BlockNum, void *pBlock, int Size);
int SubBlockToBlock(int SBB);
protected:
word ConnectionType;
longword JobStart;
TSnap7Job Job;
int DataSizeByte(int WordLength);
int opSize; // last operation size
int PerformOperation();
public:
TS7Buffer opData;
TSnap7MicroClient();
~TSnap7MicroClient();
int Reset(bool DoReconnect);
void SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTsap);
void SetConnectionType(word ConnType);
int ConnectTo(const char *RemAddress, int Rack, int Slot);
int Connect();
int Disconnect();
int GetParam(int ParamNumber, void *pValue);
int SetParam(int ParamNumber, void *pValue);
// Fundamental Data I/O functions
int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData);
int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void * pUsrData);
int ReadMultiVars(PS7DataItem Item, int ItemsCount);
int WriteMultiVars(PS7DataItem Item, int ItemsCount);
// Data I/O Helper functions
int DBRead(int DBNumber, int Start, int Size, void * pUsrData);
int DBWrite(int DBNumber, int Start, int Size, void * pUsrData);
int MBRead(int Start, int Size, void * pUsrData);
int MBWrite(int Start, int Size, void * pUsrData);
int EBRead(int Start, int Size, void * pUsrData);
int EBWrite(int Start, int Size, void * pUsrData);
int ABRead(int Start, int Size, void * pUsrData);
int ABWrite(int Start, int Size, void * pUsrData);
int TMRead(int Start, int Amount, void * pUsrData);
int TMWrite(int Start, int Amount, void * pUsrData);
int CTRead(int Start, int Amount, void * pUsrData);
int CTWrite(int Start, int Amount, void * pUsrData);
// Directory functions
int ListBlocks(PS7BlocksList pUsrData);
int GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData);
int GetPgBlockInfo(void * pBlock, PS7BlockInfo pUsrData, int Size);
int ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int & ItemsCount);
// Blocks functions
int Upload(int BlockType, int BlockNum, void * pUsrData, int & Size);
int FullUpload(int BlockType, int BlockNum, void * pUsrData, int & Size);
int Download(int BlockNum, void * pUsrData, int Size);
int Delete(int BlockType, int BlockNum);
int DBGet(int DBNumber, void * pUsrData, int & Size);
int DBFill(int DBNumber, int FillChar);
// Date/Time functions
int GetPlcDateTime(tm &DateTime);
int SetPlcDateTime(tm * DateTime);
int SetPlcSystemDateTime();
// System Info functions
int GetOrderCode(PS7OrderCode pUsrData);
int GetCpuInfo(PS7CpuInfo pUsrData);
int GetCpInfo(PS7CpInfo pUsrData);
int ReadSZL(int ID, int Index, PS7SZL pUsrData, int &Size);
int ReadSZLList(PS7SZLList pUsrData, int &ItemsCount);
// Control functions
int PlcHotStart();
int PlcColdStart();
int PlcStop();
int CopyRamToRom(int Timeout);
int Compress(int Timeout);
int GetPlcStatus(int &Status);
// Security functions
int GetProtection(PS7Protection pUsrData);
int SetSessionPassword(char *Password);
int ClearSessionPassword();
// Properties
bool Busy(){ return Job.Pending; };
int Time(){ return int(Job.Time);}
};
typedef TSnap7MicroClient *PSnap7MicroClient;
//---------------------------------------------------------------------------
#endif // s7_micro_client_h
File diff suppressed because it is too large Load Diff
+284
View File
@@ -0,0 +1,284 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_partner_h
#define s7_partner_h
//---------------------------------------------------------------------------
#include "snap_threads.h"
#include "s7_peer.h"
//---------------------------------------------------------------------------
using namespace std;
//---------------------------------------------------------------------------
#define MaxPartners 256
#define MaxAdapters 256
#define csTimeout 1500 // Connection server destruction timeout
const int par_stopped = 0; // stopped
const int par_connecting = 1; // running and active connecting
const int par_waiting = 2; // running and waiting for a connection
const int par_linked = 3; // running and connected
const int par_sending = 4; // sending data
const int par_receiving = 5; // receiving data
const int par_binderror = 6; // error starting passive partner
const longword errParMask = 0xFFF00000;
const longword errParBase = 0x000FFFFF;
const longword errParAddressInUse = 0x00200000;
const longword errParNoRoom = 0x00300000;
const longword errServerNoRoom = 0x00400000;
const longword errParInvalidParams = 0x00500000;
const longword errParNotLinked = 0x00600000;
const longword errParBusy = 0x00700000;
const longword errParFrameTimeout = 0x00800000;
const longword errParInvalidPDU = 0x00900000;
const longword errParSendTimeout = 0x00A00000;
const longword errParRecvTimeout = 0x00B00000;
const longword errParSendRefused = 0x00C00000;
const longword errParNegotiatingPDU = 0x00D00000;
const longword errParSendingBlock = 0x00E00000;
const longword errParRecvingBlock = 0x00F00000;
const longword errParBindError = 0x01000000;
const longword errParDestroying = 0x01100000;
const longword errParInvalidParamNumber = 0x01200000; // Invalid param (par_get/set_param)
const longword errParCannotChangeParam = 0x01300000; // Cannot change because running
const longword errParBufferTooSmall = 0x01400000; // Raised by LabVIEW wrapper
class TSnap7Partner;
typedef TSnap7Partner *PSnap7Partner;
class TConnectionServer;
typedef TConnectionServer *PConnectionServer;
//------------------------------------------------------------------------------
// CONNECTION SERVERS MANAGER
//------------------------------------------------------------------------------
class TServersManager
{
private:
PConnectionServer Servers[MaxAdapters];
TSnapCriticalSection *cs;
void Lock();
void Unlock();
int CreateServer(longword BindAddress, PConnectionServer &Server);
void AddServer(PConnectionServer Server);
public:
int ServersCount;
TServersManager();
~TServersManager();
int GetServer(longword BindAddress, PConnectionServer &Server);
void RemovePartner(PConnectionServer Server, PSnap7Partner Partner);
};
typedef TServersManager *PServersManager;
//------------------------------------------------------------------------------
// CONNECTION SERVER (Don't inherit from TcpSrv to avoid dependence)
//------------------------------------------------------------------------------
class TConnListenerThread : public TSnapThread
{
private:
TMsgSocket *FListener;
TConnectionServer *FServer;
public:
TConnListenerThread(TMsgSocket *Listener, TConnectionServer *Server)
{
FServer=Server;
FListener=Listener;
FreeOnTerminate=false;
};
void Execute();
};
typedef TConnListenerThread *PConnListenerThread;
class TConnectionServer
{
private:
TSnapCriticalSection *cs;
bool FRunning;
// Bind Address
char FLocalAddress[16];
// Server listener
PConnListenerThread ServerThread;
// Socket listener
PMsgSocket SockListener;
// Finds a partner bound to the address
PSnap7Partner FindPartner(longword Address);
// Locks the Partner list
void Lock();
// Unlocks the Partner list
void Unlock();
protected:
// Workers list
PSnap7Partner Partners[MaxPartners];
bool Destroying;
void Incoming(socket_t Sock);
int Start();
int FirstFree();
public:
int PartnersCount;
longword LocalBind;
TConnectionServer();
~TConnectionServer();
int StartTo(const char *Address);
void Stop();
int RegisterPartner(PSnap7Partner Partner);
void RemovePartner(PSnap7Partner Partner);
friend class TConnListenerThread;
};
typedef TConnectionServer * PConnectionServer;
//------------------------------------------------------------------------------
// PARTNER THREAD
//------------------------------------------------------------------------------
class TPartnerThread : public TSnapThread
{
private:
TSnap7Partner *FPartner;
longword FRecoveryTime;
longword FKaElapsed;
protected:
void Execute();
public:
TPartnerThread(TSnap7Partner *Partner, longword RecoveryTime)
{
FPartner = Partner;
FRecoveryTime =RecoveryTime;
FreeOnTerminate =false;
};
~TPartnerThread(){};
};
typedef TPartnerThread *PPartnerThread;
//------------------------------------------------------------------------------
// S7 PARTNER
//------------------------------------------------------------------------------
typedef struct{
bool First;
bool Done;
uintptr_t Offset;
longword TotalLength;
longword In_R_ID;
longword Elapsed;
byte Seq_Out;
}TRecvStatus;
typedef struct{
bool Done;
int Size;
int Result;
longword R_ID;
longword Count;
}TRecvLast;
extern "C" {
typedef void (S7API *pfn_ParBRecvCallBack)(void * usrPtr, int opResult, longword R_ID, void *pdata, int Size);
typedef void (S7API *pfn_ParBSendCompletion)(void * usrPtr, int opResult);
}
class TSnap7Partner : public TSnap7Peer
{
private:
PS7ReqHeader PDUH_in;
void *FRecvUsrPtr;
void *FSendUsrPtr;
PSnapEvent SendEvt;
PSnapEvent RecvEvt;
PConnectionServer FServer;
PPartnerThread FWorkerThread;
bool FSendPending;
bool FRecvPending;
TRecvStatus FRecvStatus;
TRecvLast FRecvLast;
TPendingBuffer TxBuffer;
TPendingBuffer RxBuffer;
longword FSendElapsed;
bool BindError;
byte NextByte;
pfn_ParBRecvCallBack OnBRecv;
pfn_ParBSendCompletion OnBSend;
void ClearRecv();
byte GetNextByte();
void CloseWorker();
bool BlockSend();
bool PickData();
bool BlockRecv();
bool ConnectionConfirm();
protected:
bool Stopping;
bool Execute();
void Disconnect();
bool ConnectToPeer();
bool PerformFunctionNegotiate();
public:
bool Active;
bool Running;
longword PeerAddress;
longword SrcAddress;
int BRecvTimeout;
int BSendTimeout;
longword SendTime;
longword RecvTime;
longword RecoveryTime;
longword KeepAliveTime;
longword BytesSent;
longword BytesRecv;
longword SendErrors;
longword RecvErrors;
// The partner is linked when the init sequence is terminated
//(TCP connection + ISO connection + PDU Length negotiation)
bool Linked;
TSnap7Partner(bool CreateActive);
~TSnap7Partner();
// Control
int Start();
int StartTo(const char *LocAddress, const char *RemAddress, word LocTsap, word RemTsap);
int Stop();
int Status();
int GetParam(int ParamNumber, void * pValue);
int SetParam(int ParamNumber, void * pValue);
// Block send
int BSend(longword R_ID, void *pUsrData, int Size);
int AsBSend(longword R_ID, void *pUsrData, int Size);
bool CheckAsBSendCompletion(int &opResult);
int WaitAsBSendCompletion(longword Timeout);
int SetSendCallback(pfn_ParBSendCompletion pCompletion, void *usrPtr);
// Block recv
int BRecv(longword &R_ID, void *pData, int &Size, longword Timeout);
bool CheckAsBRecvCompletion(int &opResult, longword &R_ID,
void *pData, int &Size);
int SetRecvCallback(pfn_ParBRecvCallBack pCompletion, void *usrPtr);
friend class TConnectionServer;
friend class TPartnerThread;
};
#endif // s7_partner_h
+122
View File
@@ -0,0 +1,122 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#include "s7_peer.h"
//---------------------------------------------------------------------------
TSnap7Peer::TSnap7Peer()
{
PDUH_out=PS7ReqHeader(&PDU.Payload);
PDURequest=480; // Our request, FPDULength will contain the CPU answer
LastError=0;
cntword = 0;
Destroying = false;
}
//---------------------------------------------------------------------------
TSnap7Peer::~TSnap7Peer()
{
Destroying = true;
}
//---------------------------------------------------------------------------
int TSnap7Peer::SetError(int Error)
{
if (Error==0)
ClrError();
else
LastError=Error | LastIsoError | LastTcpError;
return Error;
}
//---------------------------------------------------------------------------
void TSnap7Peer::ClrError()
{
LastError=0;
LastIsoError=0;
LastTcpError=0;
}
//---------------------------------------------------------------------------
word TSnap7Peer::GetNextWord()
{
if (cntword==0xFFFF)
cntword=0;
return cntword++;
}
//---------------------------------------------------------------------------
int TSnap7Peer::NegotiatePDULength( )
{
int Result, IsoSize = 0;
PReqFunNegotiateParams ReqNegotiate;
PResFunNegotiateParams ResNegotiate;
PS7ResHeader23 Answer;
ClrError();
// Setup Pointers
ReqNegotiate = PReqFunNegotiateParams(pbyte(PDUH_out) + sizeof(TS7ReqHeader));
// Header
PDUH_out->P = 0x32; // Always $32
PDUH_out->PDUType = PduType_request; // $01
PDUH_out->AB_EX = 0x0000; // Always $0000
PDUH_out->Sequence = GetNextWord(); // AutoInc
PDUH_out->ParLen = SwapWord(sizeof(TReqFunNegotiateParams)); // 8 bytes
PDUH_out->DataLen = 0x0000;
// Params
ReqNegotiate->FunNegotiate = pduNegotiate;
ReqNegotiate->Unknown = 0x00;
ReqNegotiate->ParallelJobs_1 = 0x0100;
ReqNegotiate->ParallelJobs_2 = 0x0100;
ReqNegotiate->PDULength = SwapWord(PDURequest);
IsoSize = sizeof( TS7ReqHeader ) + sizeof( TReqFunNegotiateParams );
Result = isoExchangeBuffer(NULL, IsoSize);
if ((Result == 0) && (IsoSize == int(sizeof(TS7ResHeader23) + sizeof(TResFunNegotiateParams))))
{
// Setup pointers
Answer = PS7ResHeader23(&PDU.Payload);
ResNegotiate = PResFunNegotiateParams(pbyte(Answer) + sizeof(TS7ResHeader23));
if ( Answer->Error != 0 )
Result = SetError(errNegotiatingPDU);
if ( Result == 0 )
PDULength = SwapWord(ResNegotiate->PDULength);
}
return Result;
}
//---------------------------------------------------------------------------
void TSnap7Peer::PeerDisconnect( )
{
ClrError();
isoDisconnect(true);
}
//---------------------------------------------------------------------------
int TSnap7Peer::PeerConnect( )
{
int Result;
ClrError();
Result = isoConnect();
if (Result == 0)
{
Result = NegotiatePDULength();
if (Result != 0)
PeerDisconnect();
}
return Result;
}
+58
View File
@@ -0,0 +1,58 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_peer_h
#define s7_peer_h
//---------------------------------------------------------------------------
#include "s7_types.h"
#include "s7_isotcp.h"
//---------------------------------------------------------------------------
const longword errPeerMask = 0xFFF00000;
const longword errPeerBase = 0x000FFFFF;
const longword errNegotiatingPDU = 0x00100000;
class TSnap7Peer: public TIsoTcpSocket
{
private:
word cntword;
protected:
bool Destroying;
PS7ReqHeader PDUH_out;
word GetNextWord();
int SetError(int Error);
int NegotiatePDULength();
void ClrError();
public:
int LastError;
int PDULength;
int PDURequest;
TSnap7Peer();
~TSnap7Peer();
void PeerDisconnect();
int PeerConnect();
};
//---------------------------------------------------------------------------
#endif
File diff suppressed because it is too large Load Diff
+261
View File
@@ -0,0 +1,261 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_server_h
#define s7_server_h
//---------------------------------------------------------------------------
#include "snap_tcpsrvr.h"
#include "s7_types.h"
#include "s7_isotcp.h"
//---------------------------------------------------------------------------
// Maximum number of DB, change it to increase/decrease the limit.
// The DB table size is 12*MaxDB bytes
#define MaxDB 2048 // Like a S7 318
#define MinPduSize 240
#define CPU315PduSize 240
//---------------------------------------------------------------------------
// Server Interface errors
const longword errSrvDBNullPointer = 0x00200000; // Pssed null as PData
const longword errSrvAreaAlreadyExists = 0x00300000; // Area Re-registration
const longword errSrvUnknownArea = 0x00400000; // Unknown area
const longword errSrvInvalidParams = 0x00500000; // Invalid param(s) supplied
const longword errSrvTooManyDB = 0x00600000; // Cannot register DB
const longword errSrvInvalidParamNumber = 0x00700000; // Invalid param (srv_get/set_param)
const longword errSrvCannotChangeParam = 0x00800000; // Cannot change because running
// Server Area ID (use with Register/unregister - Lock/unlock Area)
const int srvAreaPE = 0;
const int srvAreaPA = 1;
const int srvAreaMK = 2;
const int srvAreaCT = 3;
const int srvAreaTM = 4;
const int srvAreaDB = 5;
typedef struct{
word Number; // Number (only for DB)
word Size; // Area size (in bytes)
pbyte PData; // Pointer to area
PSnapCriticalSection cs;
}TS7Area, *PS7Area;
//------------------------------------------------------------------------------
// ISOTCP WORKER CLASS
//------------------------------------------------------------------------------
class TIsoTcpWorker : public TIsoTcpSocket
{
protected:
virtual bool IsoPerformCommand(int &Size);
virtual bool ExecuteSend();
virtual bool ExecuteRecv();
public:
TIsoTcpWorker(){};
~TIsoTcpWorker(){};
// Worker execution
bool Execute();
};
//------------------------------------------------------------------------------
// S7 WORKER CLASS
//------------------------------------------------------------------------------
// SZL frame
typedef struct{
TS7Answer17 Answer;
PReqFunReadSZLFirst ReqParams;
PS7ReqSZLData ReqData;
PS7ResParams7 ResParams;
pbyte ResData;
int ID;
int Index;
bool SZLDone;
}TSZL;
// Current Event Info
typedef struct{
word EvRetCode;
word EvArea;
word EvIndex;
word EvStart;
word EvSize;
}TEv;
// Current Block info
typedef struct{
PReqFunGetBlockInfo ReqParams;
PResFunGetBlockInfo ResParams;
TS7Answer17 Answer;
word evError;
word DataLength;
}TCB;
class TSnap7Server; // forward declaration
class TS7Worker : public TIsoTcpWorker
{
private:
PS7ReqHeader PDUH_in;
int DBCnt;
byte LastBlk;
TSZL SZL;
byte BCD(word Value);
// Checks the consistence of the incoming PDU
bool CheckPDU_in(int PayloadSize);
void FillTime(PS7Time PTime);
protected:
int DataSizeByte(int WordLength);
bool ExecuteRecv();
void DoEvent(longword Code, word RetCode, word Param1, word Param2,
word Param3, word Param4);
void DoReadEvent(longword Code, word RetCode, word Param1, word Param2,
word Param3, word Param4);
void FragmentSkipped(int Size);
// Entry parse
bool IsoPerformCommand(int &Size);
// First stage parse
bool PerformPDUAck(int &Size);
bool PerformPDURequest(int &Size);
bool PerformPDUUsrData(int &Size);
// Second stage parse : PDU Request
PS7Area GetArea(byte S7Code, word index);
// Group Read Area
bool PerformFunctionRead();
// Subfunctions Read Data
word ReadArea(PResFunReadItem ResItemData, PReqFunReadItem ReqItemPar,
int &PDURemainder,TEv &EV);
word RA_NotFound(PResFunReadItem ResItem, TEv &EV);
word RA_OutOfRange(PResFunReadItem ResItem, TEv &EV);
word RA_SizeOverPDU(PResFunReadItem ResItem, TEv &EV);
// Group Write Area
bool PerformFunctionWrite();
// Subfunctions Write Data
byte WriteArea(PReqFunWriteDataItem ReqItemData, PReqFunWriteItem ReqItemPar,
TEv &EV);
byte WA_NotFound(TEv &EV);
byte WA_InvalidTransportSize(TEv &EV);
byte WA_OutOfRange(TEv &EV);
byte WA_DataSizeMismatch(TEv &EV);
// Negotiate PDU Length
bool PerformFunctionNegotiate();
// Control
bool PerformFunctionControl(byte PduFun);
// Up/Download
bool PerformFunctionUpload();
bool PerformFunctionDownload();
// Second stage parse : PDU User data
bool PerformGroupProgrammer();
bool PerformGroupCyclicData();
bool PerformGroupSecurity();
// Group Block(s) Info
bool PerformGroupBlockInfo();
// Subfunctions Block info
void BLK_ListAll(TCB &CB);
void BLK_ListBoT(byte BlockType, bool Start, TCB &CB);
void BLK_NoResource_ListBoT(PDataFunGetBot Data, TCB &CB);
void BLK_GetBlkInfo(TCB &CB);
void BLK_NoResource_GetBlkInfo(PResDataBlockInfo Data, TCB &CB);
void BLK_GetBlockNum_GetBlkInfo(int &BlkNum, PReqDataBlockInfo ReqData);
void BLK_DoBlockInfo_GetBlkInfo(PS7Area DB, PResDataBlockInfo Data, TCB &CB);
// Clock Group
bool PerformGetClock();
bool PerformSetClock();
// SZL Group
bool PerformGroupSZL();
// Subfunctions (called by PerformGroupSZL)
void SZLNotAvailable();
void SZLSystemState();
void SZLData(void *P, int len);
void SZL_ID424();
void SZL_ID131_IDX003();
public:
TSnap7Server *FServer;
int FPDULength;
TS7Worker();
~TS7Worker(){};
};
typedef TS7Worker *PS7Worker;
//------------------------------------------------------------------------------
// S7 SERVER CLASS
//------------------------------------------------------------------------------
extern "C"
{
typedef int (S7API *pfn_RWAreaCallBack)(void *usrPtr, int Sender, int Operation, PS7Tag PTag, void *pUsrData);
}
const int OperationRead = 0;
const int OperationWrite = 1;
class TSnap7Server : public TCustomMsgServer
{
private:
// Read Callback related
pfn_SrvCallBack OnReadEvent;
pfn_RWAreaCallBack OnRWArea;
// Critical section to lock Read/Write Hook Area
PSnapCriticalSection CSRWHook;
void *FReadUsrPtr;
void *FRWAreaUsrPtr;
void DisposeAll();
int FindFirstFreeDB();
int IndexOfDB(word DBNumber);
protected:
int DBCount;
int DBLimit;
PS7Area DB[MaxDB]; // DB
PS7Area HA[5]; // MK,PE,PA,TM,CT
PS7Area FindDB(word DBNumber);
PWorkerSocket CreateWorkerSocket(socket_t Sock);
bool ResourceLess;
word ForcePDU;
int RegisterDB(word Number, void *pUsrData, word Size);
int RegisterSys(int AreaCode, void *pUsrData, word Size);
int UnregisterDB(word DBNumber);
int UnregisterSys(int AreaCode);
// The Read event
void DoReadEvent(int Sender, longword Code, word RetCode, word Param1,
word Param2, word Param3, word Param4);
bool DoReadArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData);
bool DoWriteArea(int Sender, int Area, int DBNumber, int Start, int Size, int WordLen, void *pUsrData);
public:
int WorkInterval;
byte CpuStatus;
TSnap7Server();
~TSnap7Server();
int StartTo(const char *Address);
int GetParam(int ParamNumber, void *pValue);
int SetParam(int ParamNumber, void *pValue);
int RegisterArea(int AreaCode, word Index, void *pUsrData, word Size);
int UnregisterArea(int AreaCode, word Index);
int LockArea(int AreaCode, word DBNumber);
int UnlockArea(int AreaCode, word DBNumber);
// Sets Event callback
int SetReadEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr);
int SetRWAreaCallBack(pfn_RWAreaCallBack PCallBack, void *UsrPtr);
friend class TS7Worker;
};
typedef TSnap7Server *PSnap7Server;
#endif // s7_server_h
File diff suppressed because it is too large Load Diff
+49
View File
@@ -0,0 +1,49 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef s7_text_h
#define s7_text_h
//---------------------------------------------------------------------------
#include "s7_micro_client.h"
#include "s7_server.h"
#include "s7_partner.h"
//---------------------------------------------------------------------------
const int errLibInvalidParam = -1;
const int errLibInvalidObject = -2;
// Errors areas definition
const longword ErrTcpMask = 0x0000FFFF;
const longword ErrIsoMask = 0x000F0000;
const longword ErrS7Mask = 0xFFF00000;
char* ErrCliText(int Error, char* Result, int TextLen);
char* ErrSrvText(int Error, char* Result, int TextLen);
char* ErrParText(int Error, char* Result, int TextLen);
char* EvtSrvText(TSrvEvent &Event, char* Result, int TextLen);
#endif
File diff suppressed because it is too large Load Diff
+129
View File
@@ -0,0 +1,129 @@
LIBRARY SNAP7.DLL
EXPORTS
Cli_Create
Cli_Destroy
Cli_ConnectTo
Cli_SetConnectionParams
Cli_SetConnectionType
Cli_Connect
Cli_Disconnect
Cli_GetParam
Cli_SetParam
Cli_SetAsCallback
Cli_ReadArea
Cli_WriteArea
Cli_ReadMultiVars
Cli_WriteMultiVars
Cli_DBRead
Cli_DBWrite
Cli_MBRead
Cli_MBWrite
Cli_EBRead
Cli_EBWrite
Cli_ABRead
Cli_ABWrite
Cli_TMRead
Cli_TMWrite
Cli_CTRead
Cli_CTWrite
Cli_ListBlocks
Cli_GetAgBlockInfo
Cli_GetPgBlockInfo
Cli_ListBlocksOfType
Cli_Upload
Cli_FullUpload
Cli_Download
Cli_Delete
Cli_DBGet
Cli_DBFill
Cli_GetPlcDateTime
Cli_SetPlcDateTime
Cli_SetPlcSystemDateTime
Cli_GetOrderCode
Cli_GetCpuInfo
Cli_GetCpInfo
Cli_ReadSZL
Cli_ReadSZLList
Cli_PlcHotStart
Cli_PlcColdStart
Cli_PlcStop
Cli_CopyRamToRom
Cli_Compress
Cli_GetPlcStatus
Cli_GetProtection
Cli_SetSessionPassword
Cli_ClearSessionPassword
Cli_IsoExchangeBuffer
Cli_GetExecTime
Cli_GetLastError
Cli_GetPduLength
Cli_AsReadArea
Cli_AsWriteArea
Cli_AsDBRead
Cli_AsDBWrite
Cli_AsMBRead
Cli_AsMBWrite
Cli_AsEBRead
Cli_AsEBWrite
Cli_AsABRead
Cli_AsABWrite
Cli_AsTMRead
Cli_AsTMWrite
Cli_AsCTRead
Cli_AsCTWrite
Cli_AsListBlocksOfType
Cli_AsReadSZL
Cli_AsReadSZLList
Cli_AsUpload
Cli_AsFullUpload
Cli_AsDownload
Cli_AsCopyRamToRom
Cli_AsCompress
Cli_AsDBGet
Cli_AsDBFill
Cli_CheckAsCompletion
Cli_WaitAsCompletion
Cli_ErrorText
Cli_GetConnected
Srv_Create
Srv_Destroy
Srv_GetParam
Srv_SetParam
Srv_StartTo
Srv_Start
Srv_Stop
Srv_RegisterArea
Srv_UnregisterArea
Srv_LockArea
Srv_UnlockArea
Srv_GetStatus
Srv_SetCpuStatus
Srv_ClearEvents
Srv_PickEvent
Srv_GetMask
Srv_SetMask
Srv_SetEventsCallback
Srv_SetReadEventsCallback
Srv_SetRWAreaCallback
Srv_ErrorText
Srv_EventText
Par_Create
Par_Destroy
Par_GetParam
Par_SetParam
Par_StartTo
Par_Start
Par_Stop
Par_BSend
Par_AsBSend
Par_CheckAsBSendCompletion
Par_WaitAsBSendCompletion
Par_SetSendCallback
Par_BRecv
Par_CheckAsBRecvCompletion
Par_SetRecvCallback
Par_GetTimes
Par_GetStats
Par_GetLastError
Par_GetStatus
Par_ErrorText
File diff suppressed because it is too large Load Diff
+201
View File
@@ -0,0 +1,201 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef snap7_libmain_h
#define snap7_libmain_h
//---------------------------------------------------------------------------
#include "s7_client.h"
#include "s7_server.h"
#include "s7_partner.h"
#include "s7_text.h"
//---------------------------------------------------------------------------
const int mkEvent = 0;
const int mkLog = 1;
typedef uintptr_t S7Object; // multi platform/processor object reference
//==============================================================================
// CLIENT EXPORT LIST - Sync functions
//==============================================================================
EXPORTSPEC S7Object S7API Cli_Create();
EXPORTSPEC void S7API Cli_Destroy(S7Object &Client);
EXPORTSPEC int S7API Cli_Connect(S7Object Client);
EXPORTSPEC int S7API Cli_SetConnectionParams(S7Object Client, const char *Address, word LocalTSAP, word RemoteTSAP);
EXPORTSPEC int S7API Cli_SetConnectionType(S7Object Client, word ConnectionType);
EXPORTSPEC int S7API Cli_ConnectTo(S7Object Client, const char *Address, int Rack, int Slot);
EXPORTSPEC int S7API Cli_Disconnect(S7Object Client);
EXPORTSPEC int S7API Cli_GetParam(S7Object Client, int ParamNumber, void *pValue);
EXPORTSPEC int S7API Cli_SetParam(S7Object Client, int ParamNumber, void *pValue);
EXPORTSPEC int S7API Cli_SetAsCallback(S7Object Client, pfn_CliCompletion pCompletion, void *usrPtr);
// Data I/O functions
EXPORTSPEC int S7API Cli_ReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
EXPORTSPEC int S7API Cli_WriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
EXPORTSPEC int S7API Cli_ReadMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);
EXPORTSPEC int S7API Cli_WriteMultiVars(S7Object Client, PS7DataItem Item, int ItemsCount);
// Data I/O Lean functions
EXPORTSPEC int S7API Cli_DBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_DBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_MBRead(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_MBWrite(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_EBRead(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_EBWrite(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_ABRead(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_ABWrite(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_TMRead(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_TMWrite(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_CTRead(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_CTWrite(S7Object Client, int Start, int Amount, void *pUsrData);
// Directory functions
EXPORTSPEC int S7API Cli_ListBlocks(S7Object Client, TS7BlocksList *pUsrData);
EXPORTSPEC int S7API Cli_GetAgBlockInfo(S7Object Client, int BlockType, int BlockNum, TS7BlockInfo *pUsrData);
EXPORTSPEC int S7API Cli_GetPgBlockInfo(S7Object Client, void *pBlock, TS7BlockInfo *pUsrData, int Size);
EXPORTSPEC int S7API Cli_ListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount);
// Blocks functions
EXPORTSPEC int S7API Cli_Upload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_FullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_Download(S7Object Client, int BlockNum, void *pUsrData, int Size);
EXPORTSPEC int S7API Cli_Delete(S7Object Client, int BlockType, int BlockNum);
EXPORTSPEC int S7API Cli_DBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_DBFill(S7Object Client, int DBNumber, int FillChar);
// Date/Time functions
EXPORTSPEC int S7API Cli_GetPlcDateTime(S7Object Client, tm &DateTime);
EXPORTSPEC int S7API Cli_SetPlcDateTime(S7Object Client, tm *DateTime);
EXPORTSPEC int S7API Cli_SetPlcSystemDateTime(S7Object Client);
// System Info functions
EXPORTSPEC int S7API Cli_GetOrderCode(S7Object Client, TS7OrderCode *pUsrData);
EXPORTSPEC int S7API Cli_GetCpuInfo(S7Object Client, TS7CpuInfo *pUsrData);
EXPORTSPEC int S7API Cli_GetCpInfo(S7Object Client, TS7CpInfo *pUsrData);
EXPORTSPEC int S7API Cli_ReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_ReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount);
// Control functions
EXPORTSPEC int S7API Cli_PlcHotStart(S7Object Client);
EXPORTSPEC int S7API Cli_PlcColdStart(S7Object Client);
EXPORTSPEC int S7API Cli_PlcStop(S7Object Client);
EXPORTSPEC int S7API Cli_CopyRamToRom(S7Object Client, int Timeout);
EXPORTSPEC int S7API Cli_Compress(S7Object Client, int Timeout);
EXPORTSPEC int S7API Cli_GetPlcStatus(S7Object Client, int &Status);
// Security functions
EXPORTSPEC int S7API Cli_GetProtection(S7Object Client, TS7Protection *pUsrData);
EXPORTSPEC int S7API Cli_SetSessionPassword(S7Object Client, char *Password);
EXPORTSPEC int S7API Cli_ClearSessionPassword(S7Object Client);
// Low level
EXPORTSPEC int S7API Cli_IsoExchangeBuffer(S7Object Client, void *pUsrData, int &Size);
// Misc
EXPORTSPEC int S7API Cli_GetExecTime(S7Object Client, int &Time);
EXPORTSPEC int S7API Cli_GetLastError(S7Object Client, int &LastError);
EXPORTSPEC int S7API Cli_GetPduLength(S7Object Client, int &Requested, int &Negotiated);
EXPORTSPEC int S7API Cli_ErrorText(int Error, char *Text, int TextLen);
EXPORTSPEC int S7API Cli_GetConnected(S7Object Client, int &Connected);
//==============================================================================
// CLIENT EXPORT LIST - Async functions
//==============================================================================
EXPORTSPEC int S7API Cli_AsReadArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
EXPORTSPEC int S7API Cli_AsWriteArea(S7Object Client, int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData);
EXPORTSPEC int S7API Cli_AsDBRead(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsDBWrite(S7Object Client, int DBNumber, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsMBRead(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsMBWrite(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsEBRead(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsEBWrite(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsABRead(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsABWrite(S7Object Client, int Start, int Size, void *pUsrData);
EXPORTSPEC int S7API Cli_AsTMRead(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_AsTMWrite(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_AsCTRead(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_AsCTWrite(S7Object Client, int Start, int Amount, void *pUsrData);
EXPORTSPEC int S7API Cli_AsListBlocksOfType(S7Object Client, int BlockType, TS7BlocksOfType *pUsrData, int &ItemsCount);
EXPORTSPEC int S7API Cli_AsReadSZL(S7Object Client, int ID, int Index, TS7SZL *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_AsReadSZLList(S7Object Client, TS7SZLList *pUsrData, int &ItemsCount);
EXPORTSPEC int S7API Cli_AsUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_AsFullUpload(S7Object Client, int BlockType, int BlockNum, void *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_AsDownload(S7Object Client, int BlockNum, void *pUsrData, int Size);
EXPORTSPEC int S7API Cli_AsCopyRamToRom(S7Object Client, int Timeout);
EXPORTSPEC int S7API Cli_AsCompress(S7Object Client, int Timeout);
EXPORTSPEC int S7API Cli_AsDBGet(S7Object Client, int DBNumber, void *pUsrData, int &Size);
EXPORTSPEC int S7API Cli_AsDBFill(S7Object Client, int DBNumber, int FillChar);
EXPORTSPEC int S7API Cli_CheckAsCompletion(S7Object Client, int &opResult);
EXPORTSPEC int S7API Cli_WaitAsCompletion(S7Object Client, int Timeout);
//==============================================================================
// SERVER EXPORT LIST
//==============================================================================
EXPORTSPEC S7Object S7API Srv_Create();
EXPORTSPEC void S7API Srv_Destroy(S7Object &Server);
EXPORTSPEC int S7API Srv_GetParam(S7Object Server, int ParamNumber, void *pValue);
EXPORTSPEC int S7API Srv_SetParam(S7Object Server, int ParamNumber, void *pValue);
EXPORTSPEC int S7API Srv_Start(S7Object Server);
EXPORTSPEC int S7API Srv_StartTo(S7Object Server, const char *Address);
EXPORTSPEC int S7API Srv_Stop(S7Object Server);
// Data
EXPORTSPEC int S7API Srv_RegisterArea(S7Object Server, int AreaCode, word Index, void *pUsrData, int Size);
EXPORTSPEC int S7API Srv_UnregisterArea(S7Object Server, int AreaCode, word Index);
EXPORTSPEC int S7API Srv_LockArea(S7Object Server, int AreaCode, word Index);
EXPORTSPEC int S7API Srv_UnlockArea(S7Object Server, int AreaCode, word Index);
// Events
EXPORTSPEC int S7API Srv_ClearEvents(S7Object Server);
EXPORTSPEC int S7API Srv_PickEvent(S7Object Server, TSrvEvent *pEvent, int &EvtReady);
EXPORTSPEC int S7API Srv_GetMask(S7Object Server, int MaskKind, longword &Mask);
EXPORTSPEC int S7API Srv_SetMask(S7Object Server, int MaskKind, longword Mask);
EXPORTSPEC int S7API Srv_SetEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);
EXPORTSPEC int S7API Srv_SetReadEventsCallback(S7Object Server, pfn_SrvCallBack pCallback, void *usrPtr);
EXPORTSPEC int S7API Srv_EventText(TSrvEvent &Event, char *Text, int TextLen);
EXPORTSPEC int S7API Srv_SetRWAreaCallback(S7Object Server, pfn_RWAreaCallBack pCallback, void *usrPtr);
// Misc
EXPORTSPEC int S7API Srv_GetStatus(S7Object Server, int &ServerStatus, int &CpuStatus, int &ClientsCount);
EXPORTSPEC int S7API Srv_SetCpuStatus(S7Object Server, int CpuStatus);
EXPORTSPEC int S7API Srv_ErrorText(int Error, char *Text, int TextLen);
//==============================================================================
// PARTNER EXPORT LIST
//==============================================================================
EXPORTSPEC S7Object S7API Par_Create(int Active);
EXPORTSPEC void S7API Par_Destroy(S7Object &Partner);
EXPORTSPEC int S7API Par_GetParam(S7Object Partner, int ParamNumber, void *pValue);
EXPORTSPEC int S7API Par_SetParam(S7Object Partner, int ParamNumber, void *pValue);
EXPORTSPEC int S7API Par_Start(S7Object Partner);
EXPORTSPEC int S7API Par_StartTo(S7Object Partner, const char *LocalAddress, const char *RemoteAddress,
word LocTsap, word RemTsap);
EXPORTSPEC int S7API Par_Stop(S7Object Partner);
// BSend
EXPORTSPEC int S7API Par_BSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);
EXPORTSPEC int S7API Par_AsBSend(S7Object Partner, longword R_ID, void *pUsrData, int Size);
EXPORTSPEC int S7API Par_CheckAsBSendCompletion(S7Object Partner, int &opResult);
EXPORTSPEC int S7API Par_WaitAsBSendCompletion(S7Object Partner, longword Timeout);
EXPORTSPEC int S7API Par_SetSendCallback(S7Object Partner, pfn_ParBSendCompletion pCompletion, void *usrPtr);
// BRecv
EXPORTSPEC int S7API Par_BRecv(S7Object Partner, longword &R_ID, void *pData, int &Size, longword Timeout);
EXPORTSPEC int S7API Par_CheckAsBRecvCompletion(S7Object Partner, int &opResult, longword &R_ID,
void *pData, int &Size);
EXPORTSPEC int S7API Par_SetRecvCallback(S7Object Partner, pfn_ParBRecvCallBack pCompletion, void *usrPtr);
// Stat
EXPORTSPEC int S7API Par_GetTimes(S7Object Partner, longword &SendTime, longword &RecvTime);
EXPORTSPEC int S7API Par_GetStats(S7Object Partner, longword &BytesSent, longword &BytesRecv,
longword &SendErrors, longword &RecvErrors);
EXPORTSPEC int S7API Par_GetLastError(S7Object Partner, int &LastError);
EXPORTSPEC int S7API Par_GetStatus(S7Object Partner, int &Status);
EXPORTSPEC int S7API Par_ErrorText(int Error, char *Text, int TextLen);
#endif // snap7_libmain_h
File diff suppressed because it is too large Load Diff
+339
View File
@@ -0,0 +1,339 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef snap_msgsock_h
#define snap_msgsock_h
//---------------------------------------------------------------------------
#include "snap_platform.h"
#include "snap_sysutils.h"
//----------------------------------------------------------------------------
#if defined(OS_WINDOWS) || defined (OS_SOLARIS) || defined(OS_OSX)
# define MSG_NOSIGNAL 0
#endif
//----------------------------------------------------------------------------
// Non blocking connection to avoid root priviledges under UNIX
// i.e. raw socket pinger is not more used.
// Thanks to Rolf Stalder that made it ;)
//----------------------------------------------------------------------------
#ifdef PLATFORM_UNIX
#define NON_BLOCKING_CONNECT
#endif
#ifdef NON_BLOCKING_CONNECT
#include <fcntl.h>
#endif
//----------------------------------------------------------------------------
/*
In Windows sizeof socket varies depending of the platform :
win32 -> sizeof(SOCKET) = 4
win64 -> sizeof(SOCKET) = 8
Even though sizeof(SOCKET) is 8, should be safe to cast it to int, because
the value constitutes an index in per-process table of limited size
and not a real pointer.
Other Os define the socket as int regardless of the processor.
We want to sleep peacefully, so it's better to define a portable socket.
*/
#ifdef OS_WINDOWS
typedef SOCKET socket_t;
#else
typedef int socket_t;
#endif
//----------------------------------------------------------------------------
#define SD_RECEIVE 0x00
#define SD_SEND 0x01
#define SD_BOTH 0x02
#define MaxPacketSize 65536
//----------------------------------------------------------------------------
// For other platform we need to re-define next constants
#if defined(PLATFORM_UNIX) || defined(OS_OSX)
#define INVALID_SOCKET (socket_t)(~0)
#define SOCKET_ERROR (-1)
#define WSAEINTR EINTR
#define WSAEBADF EBADF
#define WSAEACCES EACCES
#define WSAEFAULT EFAULT
#define WSAEINVAL EINVAL
#define WSAEMFILE EMFILE
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEINPROGRESS EINPROGRESS
#define WSAEALREADY EALREADY
#define WSAENOTSOCK ENOTSOCK
#define WSAEDESTADDRREQ EDESTADDRREQ
#define WSAEMSGSIZE EMSGSIZE
#define WSAEPROTOTYPE EPROTOTYPE
#define WSAENOPROTOOPT ENOPROTOOPT
#define WSAEPROTONOSUPPORT EPROTONOSUPPORT
#define WSAESOCKTNOSUPPORT ESOCKTNOSUPPORT
#define WSAEOPNOTSUPP EOPNOTSUPP
#define WSAEPFNOSUPPORT EPFNOSUPPORT
#define WSAEAFNOSUPPORT EAFNOSUPPORT
#define WSAEADDRINUSE EADDRINUSE
#define WSAEADDRNOTAVAIL EADDRNOTAVAIL
#define WSAENETDOWN ENETDOWN
#define WSAENETUNREACH ENETUNREACH
#define WSAENETRESET ENETRESET
#define WSAECONNABORTED ECONNABORTED
#define WSAECONNRESET ECONNRESET
#define WSAENOBUFS ENOBUFS
#define WSAEISCONN EISCONN
#define WSAENOTCONN ENOTCONN
#define WSAESHUTDOWN ESHUTDOWN
#define WSAETOOMANYREFS ETOOMANYREFS
#define WSAETIMEDOUT ETIMEDOUT
#define WSAECONNREFUSED ECONNREFUSED
#define WSAELOOP ELOOP
#define WSAENAMETOOLONG ENAMETOOLONG
#define WSAEHOSTDOWN EHOSTDOWN
#define WSAEHOSTUNREACH EHOSTUNREACH
#define WSAENOTEMPTY ENOTEMPTY
#define WSAEUSERS EUSERS
#define WSAEDQUOT EDQUOT
#define WSAESTALE ESTALE
#define WSAEREMOTE EREMOTE
#endif
#define WSAEINVALIDADDRESS 12001
#define ICmpBufferSize 4096
typedef byte TIcmpBuffer[ICmpBufferSize];
// Ping result
#define PR_CANNOT_PERFORM -1 // cannot ping :
// unix : no root rights or SUID flag set to
// open raw sockets
// windows : neither helper DLL found nor raw
// sockets can be opened (no administrator rights)
// In this case the execution continues whitout
// the benefit of the smart-connect.
#define PR_SUCCESS 0 // Host found
#define PR_ERROR 1 // Ping Error, Ping was performed but ...
// - host didn't replied (not found)
// - routing error
// - TTL expired
// - ... all other icmp error that we don't need
// to know.
// Ping Kind
#define pkCannotPing 1 // see PR_CANNOT_PERFORM comments
#define pkWinHelper 2 // use iphlpapi.dll (only windows)
#define pkRawSocket 3 // use raw sockets (unix/windows)
const byte ICMP_ECHORP = 0; // ECHO Reply
const byte ICMP_ECHORQ = 8; // ECHO Request
//---------------------------------------------------------------------------
// RAW SOCKET PING STRUCTS
//---------------------------------------------------------------------------
#pragma pack(1)
typedef struct{
byte ip_hl_v;
byte ip_tos;
word ip_len;
word ip_id ;
word ip_off;
byte ip_ttl;
byte ip_p;
word ip_sum;
longword ip_src;
longword ip_dst;
}TIPHeader;
typedef struct{
byte ic_type; // Type of message
byte ic_code; // Code
word ic_cksum; // 16 bit checksum
word ic_id; // ID (ic1 : ipv4)
word ic_seq; // Sequence
}TIcmpHeader;
typedef struct{
TIcmpHeader Header;
byte Data[32]; // use the well known default
}TIcmpPacket, *PIcmpPacket;
typedef struct{
TIPHeader IPH;
TIcmpPacket ICmpReply;
}TIcmpReply, *PIcmpReply;
#pragma pack()
//---------------------------------------------------------------------------
class TRawSocketPinger
{
private:
socket_t FSocket;
PIcmpPacket SendPacket;
TIcmpBuffer IcmpBuffer;
word FId, FSeq;
void InitPacket();
word PacketChecksum();
bool CanRead(int Timeout);
public:
bool Ping(longword ip_addr, int Timeout);
TRawSocketPinger();
~TRawSocketPinger();
};
typedef TRawSocketPinger *PRawSocketPinger;
//---------------------------------------------------------------------------
class TPinger
{
private:
PRawSocketPinger RawPinger;
bool RawAvail;
#ifdef OS_WINDOWS
bool WinPing(longword ip_addr, int Timeout);
#endif
bool RawPing(longword ip_addr, int Timeout);
public:
TPinger();
~TPinger();
bool Ping(char *Host, int Timeout);
bool Ping(longword ip_addr, int Timeout);
};
typedef TPinger *PPinger;
//---------------------------------------------------------------------------
class TSnapBase // base class endian-aware
{
private:
bool LittleEndian;
protected:
longword SwapDWord(longword Value);
word SwapWord(word Value);
public:
TSnapBase();
};
//---------------------------------------------------------------------------
class TMsgSocket : public TSnapBase
{
private:
PPinger Pinger;
int GetLastSocketError();
int SockCheck(int SockResult);
void DestroySocket();
void SetSocketOptions();
bool CanWrite(int Timeout);
void GetLocal();
void GetRemote();
void SetSin(sockaddr_in &sin, char *Address, u_short Port);
void GetSin(sockaddr_in sin, char *Address, u_short &Port);
protected:
socket_t FSocket;
sockaddr_in LocalSin;
sockaddr_in RemoteSin;
//--------------------------------------------------------------------------
// low level socket
void CreateSocket();
// Called when a socket is assigned externally
void GotSocket();
// Returns how many bytes are ready to be read in the winsock buffer
int WaitingData();
// Waits until there at least "size" bytes ready to be read or until receive timeout occurs
int WaitForData(int Size, int Timeout);
// Clear socket input buffer
void Purge();
public:
longword ClientHandle;
longword LocalBind;
// Coordinates Address:Port
char LocalAddress[16];
char RemoteAddress[16];
word LocalPort;
word RemotePort;
// "speed" of the socket listener (used server-side)
int WorkInterval;
// Timeouts : 3 different values for fine tuning.
// Send timeout should be small since with work with small packets and TCP_NO_DELAY
// option, so we don't expect "time to wait".
// Recv timeout depends of equipment's processing time : we send a packet, the equipment
// processes the message, finally it sends the answer. In any case Recv timeout > Send Timeout.
// PingTimeout is the maximum time interval during which we expect that the PLC answers.
// By default is 750 ms, increase it if there are many switch/repeaters.
int PingTimeout;
int RecvTimeout;
int SendTimeout;
//int ConnTimeout;
// Output : Last operation error
int LastTcpError;
// Output : Connected to the remote Host/Peer/Client
bool Connected;
//--------------------------------------------------------------------------
TMsgSocket();
virtual ~TMsgSocket();
// Returns true if "something" can be read during the Timeout interval..
bool CanRead(int Timeout);
// Connects to a peer (using RemoteAddress and RemotePort)
int SckConnect(); // (client-side)
// Disconnects from a peer (gracefully)
void SckDisconnect();
// Disconnects RAW
void ForceClose();
// Binds to a local adapter (using LocalAddress and LocalPort) (server-side)
int SckBind();
// Listens for an incoming connection (server-side)
int SckListen();
// Set an external socket reference (tipically from a listener)
void SetSocket(socket_t s);
// Accepts an incoming connection returning a socket descriptor (server-side)
socket_t SckAccept();
// Pings the peer before connecting
bool Ping(char *Host);
bool Ping(sockaddr_in Addr);
// Sends a packet
int SendPacket(void *Data, int Size);
// Returns true if a Packet at least of "Size" bytes is ready to be read
bool PacketReady(int Size);
// Receives everything
int Receive(void *Data, int BufSize, int & SizeRecvd);
// Receives a packet of size specified.
int RecvPacket(void *Data, int Size);
// Peeks a packet of size specified without extract it from the socket queue
int PeekPacket(void *Data, int Size);
virtual bool Execute();
};
typedef TMsgSocket *PMsgSocket;
//---------------------------------------------------------------------------
void Msg_CloseSocket(socket_t FSocket);
longword Msg_GetSockAddr(socket_t FSocket);
//---------------------------------------------------------------------------
class SocketsLayer
{
private:
#ifdef OS_WINDOWS
WSADATA wsaData;
#endif
public:
SocketsLayer();
~SocketsLayer();
};
#endif // snap_msgsock_h
+152
View File
@@ -0,0 +1,152 @@
/*=============================================================================|
| PROJECT SNAP7 1.4.1 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef snap_platform_h
#define snap_platform_h
//---------------------------------------------------------------------------
#if defined (_WIN32)|| defined(_WIN64)|| defined(__WIN32__) || defined(__WINDOWS__)
# define OS_WINDOWS
#endif
// Visual Studio needs this to use the correct time_t size
#if defined (_WIN32) && !defined(_WIN64) && !defined(_EMBEDDING_VS2013UP)
# define _USE_32BIT_TIME_T
#endif
// Linux, BSD and Solaris define "unix", OSX doesn't, even though it derives from BSD
#if defined(unix) || defined(__unix__) || defined(__unix)
# define PLATFORM_UNIX
#endif
#if BSD>=0
# define OS_BSD
#endif
#if __APPLE__
# define OS_OSX
#endif
#if defined(__SVR4) || defined(__svr4__)
# define OS_SOLARIS
// Thanks to Rolf Stalder now it's possible to use pthreads also for Solaris
// In any case the Solaris native threads model is still present and can be
// used uncommenting the #define line below.
# undef OS_SOLARIS_NATIVE_THREADS
// # define OS_SOLARIS_NATIVE_THREADS
#endif
#if defined(PLATFORM_UNIX)
# include <unistd.h>
# include <sys/param.h>
# if defined(_POSIX_VERSION)
# define POSIX
# endif
#endif
#ifdef OS_OSX
# include <unistd.h>
#endif
#if (!defined (OS_WINDOWS)) && (!defined(PLATFORM_UNIX)) && (!defined(OS_BSD)) && (!defined(OS_OSX))
# error platform still unsupported (please add it yourself and report ;-)
#endif
// Visual C++ not C99 compliant (VS2008--)
#ifdef _MSC_VER
# if _MSC_VER >= 1600
# include <stdint.h> // VS2010++ have it
# else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef signed __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef unsigned __int32 uintptr_t;
#endif
# endif
#else
# include <stdint.h>
#endif
#include <time.h>
#include <cstring>
#include <stdlib.h>
#ifdef OS_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <winsock2.h>
# include <mmsystem.h>
#endif
#ifdef OS_SOLARIS
# include <sys/filio.h>
# include <cstdlib>
# include <string.h>
#endif
#if defined(PLATFORM_UNIX) || defined(OS_OSX)
# include <errno.h>
# include <sys/time.h>
# include <sys/socket.h>
# include <arpa/inet.h>
# include <netinet/tcp.h>
# include <netinet/in.h>
# include <sys/ioctl.h>
#endif
#ifdef OS_WINDOWS
# define EXPORTSPEC extern "C" __declspec ( dllexport )
# define S7API __stdcall
#else
# define EXPORTSPEC extern "C"
# define S7API
#endif
// Exact length types regardless of platform/processor
// We absolute need of them, all structs have an exact size that
// must be the same across the processor used 32/64 bit
// *Use them* if you change/expand the code and avoid long, u_long and so on...
typedef uint8_t byte;
typedef uint16_t word;
typedef uint32_t longword;
typedef byte *pbyte;
typedef word *pword;
typedef uintptr_t snap_obj; // multi platform/processor object reference
#ifndef OS_WINDOWS
# define INFINITE 0XFFFFFFFF
#endif
#endif // snap_platform_h
+73
View File
@@ -0,0 +1,73 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#include "snap_sysutils.h"
#ifdef OS_OSX
int clock_gettime(int clk_id, struct timespec* t)
{
struct timeval now;
int rv = gettimeofday(&now, NULL);
if (rv) return rv;
t->tv_sec = now.tv_sec;
t->tv_nsec = now.tv_usec * 1000;
return 0;
}
#endif
//---------------------------------------------------------------------------
longword SysGetTick()
{
#ifdef OS_WINDOWS
return timeGetTime();
#else
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (longword) (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
#endif
}
//---------------------------------------------------------------------------
void SysSleep(longword Delay_ms)
{
#ifdef OS_WINDOWS
Sleep(Delay_ms);
#else
struct timespec ts;
ts.tv_sec = (time_t)(Delay_ms / 1000);
ts.tv_nsec =(long)((Delay_ms - ts.tv_sec) * 1000000);
nanosleep(&ts, (struct timespec *)0);
#endif
}
//---------------------------------------------------------------------------
longword DeltaTime(longword &Elapsed)
{
longword TheTime;
TheTime=SysGetTick();
// Checks for rollover
if (TheTime<Elapsed)
Elapsed=0;
return TheTime-Elapsed;
}
+39
View File
@@ -0,0 +1,39 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef snap_sysutils_h
#define snap_sysutils_h
//---------------------------------------------------------------------------
#include "snap_platform.h"
//---------------------------------------------------------------------------
#ifdef OS_OSX
# define CLOCK_MONOTONIC 0
#endif
longword SysGetTick();
void SysSleep(longword Delay_ms);
longword DeltaTime(longword &Elapsed);
#endif // snap_sysutils_h
+487
View File
@@ -0,0 +1,487 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#include "snap_tcpsrvr.h"
//---------------------------------------------------------------------------
// EVENTS QUEUE
//---------------------------------------------------------------------------
TMsgEventQueue::TMsgEventQueue(const int Capacity, const int BlockSize)
{
FCapacity = Capacity;
Max = FCapacity - 1;
FBlockSize = BlockSize;
Buffer = new byte[FCapacity * FBlockSize];
Flush();
}
//---------------------------------------------------------------------------
TMsgEventQueue::~TMsgEventQueue()
{
delete[] Buffer;
}
//---------------------------------------------------------------------------
void TMsgEventQueue::Flush()
{
IndexIn = 0;
IndexOut = 0;
}
//---------------------------------------------------------------------------
void TMsgEventQueue::Insert(void *lpdata)
{
pbyte PBlock;
if (!Full())
{
// Calc offset
if (IndexIn < Max) IndexIn++;
else IndexIn = 0;
PBlock = Buffer + uintptr_t(IndexIn * FBlockSize);
memcpy(PBlock, lpdata, FBlockSize);
};
}
//---------------------------------------------------------------------------
bool TMsgEventQueue::Extract(void *lpdata)
{
int IdxOut;
pbyte PBlock;
if (!Empty())
{
// stores IndexOut
IdxOut = IndexOut;
if (IdxOut < Max) IdxOut++;
else IdxOut = 0;
PBlock = Buffer + uintptr_t(IdxOut * FBlockSize);
// moves data
memcpy(lpdata, PBlock, FBlockSize);
// Updates IndexOut
IndexOut = IdxOut;
return true;
}
else
return false;
}
//---------------------------------------------------------------------------
bool TMsgEventQueue::Empty()
{
return (IndexIn == IndexOut);
}
//---------------------------------------------------------------------------
bool TMsgEventQueue::Full()
{
int IdxOut = IndexOut; // To avoid troubles if IndexOut changes during next line
return ( (IdxOut == IndexIn + 1) || ((IndexIn == Max) && (IdxOut == 0)));
}
//---------------------------------------------------------------------------
// WORKER THREAD
//---------------------------------------------------------------------------
TMsgWorkerThread::TMsgWorkerThread(TMsgSocket *Socket, TCustomMsgServer *Server)
{
FreeOnTerminate = true;
WorkerSocket = Socket;
FServer = Server;
}
//---------------------------------------------------------------------------
void TMsgWorkerThread::Execute()
{
bool Exception = false;
bool SelfClose = false;
// Working loop
while (!Terminated && !SelfClose && !Exception && !FServer->Destroying)
{
try
{
if (!WorkerSocket->Execute()) // False -> End of Activities
SelfClose = true;
} catch (...)
{
Exception = true;
}
};
if (!FServer->Destroying)
{
// Exception detected during Worker activity
if (Exception)
{
WorkerSocket->ForceClose();
FServer->DoEvent(WorkerSocket->ClientHandle, evcClientException, 0, 0, 0, 0, 0);
}
else
if (SelfClose)
{
FServer->DoEvent(WorkerSocket->ClientHandle, evcClientDisconnected, 0, 0, 0, 0, 0);
}
else
FServer->DoEvent(WorkerSocket->ClientHandle, evcClientTerminated, 0, 0, 0, 0, 0);
}
delete WorkerSocket;
// Delete reference from list
FServer->Delete(Index);
}
//---------------------------------------------------------------------------
// LISTENER THREAD
//---------------------------------------------------------------------------
TMsgListenerThread::TMsgListenerThread(TMsgSocket *Listener, TCustomMsgServer *Server)
{
FServer = Server;
FListener = Listener;
FreeOnTerminate = false;
}
//---------------------------------------------------------------------------
void TMsgListenerThread::Execute()
{
socket_t Sock;
bool Valid;
while (!Terminated)
{
if (FListener->CanRead(FListener->WorkInterval))
{
Sock = FListener->SckAccept(); // in any case we must accept
Valid = Sock != INVALID_SOCKET;
// check if we are not destroying
if ((!Terminated) && (!FServer->Destroying))
{
if (Valid)
FServer->Incoming(Sock);
}
else
if (Valid)
Msg_CloseSocket(Sock);
};
}
}
//---------------------------------------------------------------------------
// TCP SERVER
//---------------------------------------------------------------------------
TCustomMsgServer::TCustomMsgServer()
{
strcpy(FLocalAddress, "0.0.0.0");
CSList = new TSnapCriticalSection();
CSEvent = new TSnapCriticalSection();
FEventQueue = new TMsgEventQueue(MaxEvents, sizeof (TSrvEvent));
memset(Workers, 0, sizeof (Workers));
for (int i = 0; i < MaxWorkers; i++)
Workers[i] = NULL;
Status = SrvStopped;
EventMask = 0xFFFFFFFF;
LogMask = 0xFFFFFFFF;
Destroying = false;
FLastError = 0;
ClientsCount = 0;
LocalBind = 0;
MaxClients = MaxWorkers;
OnEvent = NULL;
}
//---------------------------------------------------------------------------
TCustomMsgServer::~TCustomMsgServer()
{
Destroying = true;
Stop();
OnEvent = NULL;
delete CSList;
delete CSEvent;
delete FEventQueue;
}
//---------------------------------------------------------------------------
void TCustomMsgServer::LockList()
{
CSList->Enter();
}
//---------------------------------------------------------------------------
void TCustomMsgServer::UnlockList()
{
CSList->Leave();
}
//---------------------------------------------------------------------------
int TCustomMsgServer::FirstFree()
{
int i;
for (i = 0; i < MaxWorkers; i++)
{
if (Workers[i] == 0)
return i;
}
return -1;
}
//---------------------------------------------------------------------------
int TCustomMsgServer::StartListener()
{
int Result;
// Creates the listener
SockListener = new TMsgSocket();
strncpy(SockListener->LocalAddress, FLocalAddress, 16);
SockListener->LocalPort = LocalPort;
// Binds
Result = SockListener->SckBind();
if (Result == 0)
{
LocalBind = SockListener->LocalBind;
// Listen
Result = SockListener->SckListen();
if (Result == 0)
{
// Creates the Listener thread
ServerThread = new TMsgListenerThread(SockListener, this);
ServerThread->Start();
}
else
delete SockListener;
}
else
delete SockListener;
return Result;
}
//---------------------------------------------------------------------------
void TCustomMsgServer::TerminateAll()
{
int c;
longword Elapsed;
bool Timeout;
if (ClientsCount > 0)
{
for (c = 0; c < MaxWorkers; c++)
{
if (Workers[c] != 0)
PMsgWorkerThread(Workers[c])->Terminate();
}
// Wait for closing
Elapsed = SysGetTick();
Timeout = false;
while (!Timeout && (ClientsCount > 0))
{
Timeout = DeltaTime(Elapsed) > WkTimeout;
if (!Timeout)
SysSleep(100);
};
if (ClientsCount > 0)
KillAll(); // one o more threads are hanged
ClientsCount = 0;
}
}
//---------------------------------------------------------------------------
void TCustomMsgServer::KillAll()
{
int c, cnt = 0;
LockList();
for (c = 0; c < MaxWorkers; c++)
{
if (Workers[c] != 0)
try
{
PMsgWorkerThread(Workers[c])->Kill();
PMsgWorkerThread(Workers[c])->WorkerSocket->ForceClose();
delete PMsgWorkerThread(Workers[c]);
Workers[c] = 0;
cnt++;
} catch (...)
{
};
}
UnlockList();
DoEvent(0, evcClientsDropped, 0, cnt, 0, 0, 0);
}
//---------------------------------------------------------------------------
bool TCustomMsgServer::CanAccept(socket_t Socket)
{
return ((MaxClients == 0) || (ClientsCount < MaxClients));
}
//---------------------------------------------------------------------------
PWorkerSocket TCustomMsgServer::CreateWorkerSocket(socket_t Sock)
{
PWorkerSocket Result;
// Creates a funny default class : a tcp echo worker
Result = new TEcoTcpWorker();
Result->SetSocket(Sock);
return Result;
}
//---------------------------------------------------------------------------
void TCustomMsgServer::DoEvent(int Sender, longword Code, word RetCode, word Param1, word Param2, word Param3, word Param4)
{
TSrvEvent SrvEvent;
bool GoLog = (Code & LogMask) != 0;
bool GoEvent = (Code & EventMask) != 0;
if (!Destroying && (GoLog || GoEvent))
{
CSEvent->Enter();
time(&SrvEvent.EvtTime);
SrvEvent.EvtSender = Sender;
SrvEvent.EvtCode = Code;
SrvEvent.EvtRetCode = RetCode;
SrvEvent.EvtParam1 = Param1;
SrvEvent.EvtParam2 = Param2;
SrvEvent.EvtParam3 = Param3;
SrvEvent.EvtParam4 = Param4;
if (GoEvent && (OnEvent != NULL))
try
{ // callback is outside here, we have to shield it
OnEvent(FUsrPtr, &SrvEvent, sizeof (TSrvEvent));
} catch (...)
{
};
if (GoLog)
FEventQueue->Insert(&SrvEvent);
CSEvent->Leave();
};
}
//---------------------------------------------------------------------------
void TCustomMsgServer::Delete(int Index)
{
LockList();
Workers[Index] = 0;
ClientsCount--;
UnlockList();
}
//---------------------------------------------------------------------------
void TCustomMsgServer::Incoming(socket_t Sock)
{
int idx;
PWorkerSocket WorkerSocket;
longword ClientHandle = Msg_GetSockAddr(Sock);
if (CanAccept(Sock))
{
LockList();
// First position available in the thread buffer
idx = FirstFree();
if (idx >= 0)
{
// Creates the Worker and assigns it the connected socket
WorkerSocket = CreateWorkerSocket(Sock);
// Creates the Worker thread
Workers[idx] = new TMsgWorkerThread(WorkerSocket, this);
PMsgWorkerThread(Workers[idx])->Index = idx;
// Update the number
ClientsCount++;
// And Starts the worker
PMsgWorkerThread(Workers[idx])->Start();
DoEvent(WorkerSocket->ClientHandle, evcClientAdded, 0, 0, 0, 0, 0);
}
else
{
DoEvent(ClientHandle, evcClientNoRoom, 0, 0, 0, 0, 0);
Msg_CloseSocket(Sock);
}
UnlockList();
}
else
{
Msg_CloseSocket(Sock);
DoEvent(ClientHandle, evcClientRejected, 0, 0, 0, 0, 0);
};
}
//---------------------------------------------------------------------------
int TCustomMsgServer::Start()
{
int Result = 0;
if (Status != SrvRunning)
{
Result = StartListener();
if (Result != 0)
{
DoEvent(0, evcListenerCannotStart, Result, 0, 0, 0, 0);
Status = SrvError;
}
else
{
DoEvent(0, evcServerStarted, SockListener->ClientHandle, LocalPort, 0, 0, 0);
Status = SrvRunning;
};
};
FLastError = Result;
return Result;
}
//---------------------------------------------------------------------------
int TCustomMsgServer::StartTo(const char *Address, word Port)
{
strncpy(FLocalAddress, Address, 16);
LocalPort = Port;
return Start();
}
//---------------------------------------------------------------------------
void TCustomMsgServer::Stop()
{
if (Status == SrvRunning)
{
// Kills the listener thread
ServerThread->Terminate();
if (ServerThread->WaitFor(ThTimeout) != WAIT_OBJECT_0)
ServerThread->Kill();
delete ServerThread;
// Kills the listener
delete SockListener;
// Terminate all client threads
TerminateAll();
Status = SrvStopped;
LocalBind = 0;
DoEvent(0, evcServerStopped, 0, 0, 0, 0, 0);
};
FLastError = 0;
}
//---------------------------------------------------------------------------
int TCustomMsgServer::SetEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr)
{
OnEvent = PCallBack;
FUsrPtr = UsrPtr;
return 0;
}
//---------------------------------------------------------------------------
bool TCustomMsgServer::PickEvent(void *pEvent)
{
try
{
return FEventQueue->Extract(pEvent);
} catch (...)
{
return false;
};
}
//---------------------------------------------------------------------------
bool TCustomMsgServer::EventEmpty()
{
return FEventQueue->Empty();
}
//---------------------------------------------------------------------------
void TCustomMsgServer::EventsFlush()
{
CSEvent->Enter();
FEventQueue->Flush();
CSEvent->Leave();
}
//---------------------------------------------------------------------------
+247
View File
@@ -0,0 +1,247 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef snap_tcpsrvr_h
#define snap_tcpsrvr_h
//---------------------------------------------------------------------------
#include "snap_msgsock.h"
#include "snap_threads.h"
//---------------------------------------------------------------------------
#define MaxWorkers 1024
#define MaxEvents 1500
const int SrvStopped = 0;
const int SrvRunning = 1;
const int SrvError = 2;
const longword evcServerStarted = 0x00000001;
const longword evcServerStopped = 0x00000002;
const longword evcListenerCannotStart = 0x00000004;
const longword evcClientAdded = 0x00000008;
const longword evcClientRejected = 0x00000010;
const longword evcClientNoRoom = 0x00000020;
const longword evcClientException = 0x00000040;
const longword evcClientDisconnected = 0x00000080;
const longword evcClientTerminated = 0x00000100;
const longword evcClientsDropped = 0x00000200;
const longword evcReserved_00000400 = 0x00000400;
const longword evcReserved_00000800 = 0x00000800;
const longword evcReserved_00001000 = 0x00001000;
const longword evcReserved_00002000 = 0x00002000;
const longword evcReserved_00004000 = 0x00004000;
const longword evcReserved_00008000 = 0x00008000;
// Server Interface errors
const longword errSrvBase = 0x0000FFFF;
const longword errSrvMask = 0xFFFF0000;
const longword errSrvCannotStart = 0x00100000;
const longword ThTimeout = 2000; // Thread timeout
const longword WkTimeout = 3000; // Workers termination timeout
#pragma pack(1)
typedef struct{
time_t EvtTime; // Timestamp
int EvtSender; // Sender
longword EvtCode; // Event code
word EvtRetCode; // Event result
word EvtParam1; // Param 1 (if available)
word EvtParam2; // Param 2 (if available)
word EvtParam3; // Param 3 (if available)
word EvtParam4; // Param 4 (if available)
}TSrvEvent, *PSrvEvent;
extern "C"
{
typedef void (S7API *pfn_SrvCallBack)(void * usrPtr, PSrvEvent PEvent, int Size);
}
#pragma pack()
//---------------------------------------------------------------------------
// EVENTS QUEUE
//---------------------------------------------------------------------------
class TMsgEventQueue
{
private:
int IndexIn; // <-- insert index
int IndexOut; // --> extract index
int Max; // Buffer upper bound [0..Max]
int FCapacity; // Queue capacity
pbyte Buffer;
int FBlockSize;
public:
TMsgEventQueue(const int Capacity, const int BlockSize);
~TMsgEventQueue();
void Flush();
void Insert(void *lpdata);
bool Extract(void *lpdata);
bool Empty();
bool Full();
};
typedef TMsgEventQueue *PMsgEventQueue;
//---------------------------------------------------------------------------
// WORKER THREAD
//---------------------------------------------------------------------------
class TCustomMsgServer; // forward declaration
// It's created when connection is accepted, it will interface with the client.
class TMsgWorkerThread : public TSnapThread
{
private:
TCustomMsgServer *FServer;
protected:
TMsgSocket *WorkerSocket;
public:
int Index;
friend class TCustomMsgServer;
TMsgWorkerThread(TMsgSocket *Socket, TCustomMsgServer *Server);
void Execute();
};
typedef TMsgWorkerThread *PMsgWorkerThread;
//---------------------------------------------------------------------------
// LISTENER THREAD
//---------------------------------------------------------------------------
// It listens for incoming connection.
class TMsgListenerThread : public TSnapThread
{
private:
TMsgSocket *FListener;
TCustomMsgServer *FServer;
public:
TMsgListenerThread(TMsgSocket *Listener, TCustomMsgServer *Server);
void Execute();
};
typedef TMsgListenerThread *PMsgListenerThread;
//---------------------------------------------------------------------------
// TCP SERVER
//---------------------------------------------------------------------------
typedef TMsgSocket *PWorkerSocket;
class TCustomMsgServer
{
private:
int FLastError;
char FLocalAddress[16];
// Socket listener
PMsgSocket SockListener;
// Server listener
PMsgListenerThread ServerThread;
// Critical section to lock Workers list activities
PSnapCriticalSection CSList;
// Event queue
PMsgEventQueue FEventQueue;
// Callback related
pfn_SrvCallBack OnEvent;
void *FUsrPtr;
// private methods
int StartListener();
void LockList();
void UnlockList();
int FirstFree();
protected:
bool Destroying;
// Critical section to lock Event activities
PSnapCriticalSection CSEvent;
// Workers list
void *Workers[MaxWorkers];
// Terminates all worker threads
virtual void TerminateAll();
// Kills all worker threads that are unresponsive
void KillAll();
// if (true the connection is accepted, otherwise the connection
// is closed gracefully
virtual bool CanAccept(socket_t Socket);
// Returns the class of the worker socket, override it for real servers
virtual PWorkerSocket CreateWorkerSocket(socket_t Sock);
// Handles the event
virtual void DoEvent(int Sender, longword Code, word RetCode, word Param1,
word Param2, word Param3, word Param4);
// Delete the worker from the list (It's invoked by Worker Thread)
void Delete(int Index);
// Incoming connection (It's invoked by ServerThread, the listener)
virtual void Incoming(socket_t Sock);
public:
friend class TMsgWorkerThread;
friend class TMsgListenerThread;
word LocalPort;
longword LocalBind;
longword LogMask;
longword EventMask;
int Status;
int ClientsCount;
int MaxClients;
TCustomMsgServer();
virtual ~TCustomMsgServer();
// Starts the server
int Start();
int StartTo(const char *Address, word Port);
// Stops the server
void Stop();
// Sets Event callback
int SetEventsCallBack(pfn_SrvCallBack PCallBack, void *UsrPtr);
// Pick an event from the circular queue
bool PickEvent(void *pEvent);
// Returns true if (the Event queue is empty
bool EventEmpty();
// Flushes Event queue
void EventsFlush();
};
//---------------------------------------------------------------------------
// TCP WORKER
//---------------------------------------------------------------------------
// Default worker class, a simply tcp echo to test the connection and
// data I/O to use the server outside the project
class TEcoTcpWorker : public TMsgSocket
{
public:
bool Execute()
{
byte Buffer[4096];
int Size;
if (CanRead(WorkInterval)) // Small time to avoid time wait during the close
{
Receive(&Buffer,sizeof(Buffer),Size);
if ((LastTcpError==0) && (Size>0))
{
SendPacket(&Buffer,Size);
return LastTcpError==0;
}
else
return false;
}
else
return true;
};
};
//---------------------------------------------------------------------------
#endif // snap_tcpsrvr_h
+162
View File
@@ -0,0 +1,162 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#include "snap_threads.h"
//---------------------------------------------------------------------------
#ifdef OS_WINDOWS
DWORD WINAPI ThreadProc(LPVOID param)
#else
void* ThreadProc(void* param)
#endif
{
PSnapThread Thread;
// Unix but not Solaris
#if (defined(POSIX) || defined(OS_OSX)) && (!defined(OS_SOLARIS_NATIVE_THREADS))
int last_type, last_state;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
#endif
Thread = PSnapThread(param);
if (!Thread->Terminated)
try
{
Thread->Execute();
} catch (...)
{
};
Thread->Closed = true;
if (Thread->FreeOnTerminate)
{
delete Thread;
};
#ifdef OS_WINDOWS
ExitThread(0);
#endif
#if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS))
pthread_exit((void*)0);
#endif
#if defined(OS_OSX)
pthread_exit((void*)0);
#endif
#ifdef OS_SOLARIS_NATIVE_THREADS
thr_exit((void*)0);
#endif
return 0; // never reach, only to avoid compiler warning
}
//---------------------------------------------------------------------------
TSnapThread::TSnapThread()
{
Started = false;
Closed=false;
Terminated = false;
FreeOnTerminate = false;
}
//---------------------------------------------------------------------------
TSnapThread::~TSnapThread()
{
if (Started && !Closed)
{
Terminate();
Join();
};
#ifdef OS_WINDOWS
if (Started)
CloseHandle(th);
#endif
}
//---------------------------------------------------------------------------
void TSnapThread::ThreadCreate()
{
#ifdef OS_WINDOWS
th = CreateThread(0, 0, ThreadProc, this, 0, 0);
#endif
#if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS))
pthread_attr_t a;
pthread_attr_init(&a);
pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED);
pthread_create(&th, &a, &ThreadProc, this);
#endif
#if defined(OS_OSX)
pthread_create(&th, 0, &ThreadProc, this);
#endif
#ifdef OS_SOLARIS_NATIVE_THREADS
thr_create(0, // default stack base
0, // default stack size
&ThreadProc, // Thread routine
this, // argument
0,
&th);
#endif
}
//---------------------------------------------------------------------------
void TSnapThread::Start()
{
if (!Started)
{
ThreadCreate();
Started = true;
}
}
//---------------------------------------------------------------------------
void TSnapThread::Terminate()
{
Terminated = true;
}
//---------------------------------------------------------------------------
void TSnapThread::Kill()
{
if (Started && !Closed)
{
ThreadKill();
Closed = true;
}
}
//---------------------------------------------------------------------------
void TSnapThread::Join()
{
if (Started && !Closed)
{
ThreadJoin();
Closed = true;
}
}
//---------------------------------------------------------------------------
longword TSnapThread::WaitFor(uint64_t Timeout)
{
if (Started)
{
if (!Closed)
return ThreadWait(Timeout);
else
return WAIT_OBJECT_0;
}
else
return WAIT_OBJECT_0;
}
//---------------------------------------------------------------------------
+45
View File
@@ -0,0 +1,45 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|=============================================================================*/
#ifndef snap_threads_h
#define snap_threads_h
//---------------------------------------------------------------------------
#include "snap_platform.h"
#ifdef OS_WINDOWS
# include "win_threads.h"
#endif
#if defined(POSIX) && (!defined(OS_SOLARIS_NATIVE_THREADS))
# include "unix_threads.h"
#endif
#ifdef OS_SOLARIS_NATIVE_THREADS
# include "sol_threads.h"
#endif
#if defined(OS_OSX)
# include "unix_threads.h"
#endif
//---------------------------------------------------------------------------
#endif // snap_threads_h
+208
View File
@@ -0,0 +1,208 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|==============================================================================|
| |
| Solaris 11 Threads support |
| |
|=============================================================================*/
#ifndef sol_threads_h
#define sol_threads_h
//---------------------------------------------------------------------------
#include "snap_platform.h"
#include "snap_sysutils.h"
#include <thread.h>
#include <synch.h>
//---------------------------------------------------------------------------
class TSnapCriticalSection {
private:
mutex_t mx;
int result;
public:
TSnapCriticalSection() {
mutex_init(&mx, USYNC_THREAD, 0);
};
~TSnapCriticalSection() {
mutex_destroy(&mx);
};
void Enter() {
mutex_lock(&mx);
};
void Leave() {
mutex_unlock(&mx);
};
bool TryEnter() {
return mutex_trylock(&mx) == 0;
};
};
typedef TSnapCriticalSection *PSnapCriticalSection;
//---------------------------------------------------------------------------
const longword WAIT_OBJECT_0 = 0x00000000L;
const longword WAIT_ABANDONED = 0x00000080L;
const longword WAIT_TIMEOUT = 0x00000102L;
const longword WAIT_FAILED = 0xFFFFFFFFL;
class TSnapEvent {
private:
cond_t CVariable;
mutex_t Mutex;
bool AutoReset;
bool State;
public:
TSnapEvent(bool ManualReset)
{
AutoReset = !ManualReset;
cond_init(&CVariable, USYNC_THREAD, 0) == 0;
mutex_init(&Mutex, USYNC_THREAD, 0);
State = false;
}
~TSnapEvent()
{
cond_destroy(&CVariable);
mutex_destroy(&Mutex);
};
void Set()
{
mutex_lock(&Mutex);
State = true;
if (AutoReset)
cond_signal(&CVariable);
else
cond_broadcast(&CVariable);
mutex_unlock(&Mutex);
};
void Reset()
{
mutex_lock(&Mutex);
State = false;
mutex_unlock(&Mutex);
}
longword WaitForever()
{
mutex_lock(&Mutex);
while (!State) // <-- to avoid spurious wakeups
cond_wait(&CVariable, &Mutex);
if (AutoReset)
State = false;
mutex_unlock(&Mutex);
return WAIT_OBJECT_0;
};
longword WaitFor(int64_t Timeout)
{
longword Result = WAIT_OBJECT_0;
if (Timeout == 0)
Timeout = 1; // 0 is not allowed
if (Timeout > 0) {
mutex_lock(&Mutex);
if (!State) {
timespec ts;
timeval tv;
gettimeofday(&tv, NULL);
uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 +
Timeout * 1000000 +
((uint64_t) tv.tv_usec) * 1000;
ts.tv_sec = nsecs / 1000000000;
ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000);
do
{
Result = cond_timedwait(&CVariable, &Mutex, &ts);
if (Result == ETIMEDOUT)
Result = WAIT_TIMEOUT;
}
while (Result == 0 && !State);
}
else
if (AutoReset) // take the ownership
State = false;
mutex_unlock(&Mutex);
return Result;
}
else // Timeout<0
return WaitForever();
};
};
typedef TSnapEvent *PSnapEvent;
//---------------------------------------------------------------------------
class TSnapThread {
private:
thread_t th;
bool FCreateSuspended;
void ThreadCreate();
void ThreadJoin()
{
thr_join(th, 0, 0);
};
void ThreadKill()
{
thr_kill(th, 0);
};
longword ThreadWait(uint64_t Timeout)
{
longword Elapsed = SysGetTick();
while (!Closed && !(DeltaTime(Elapsed) > Timeout))
SysSleep(100);
if (Closed)
return WAIT_OBJECT_0;
else
return WAIT_TIMEOUT;
};
protected:
bool Started;
public:
bool Terminated;
bool Closed;
bool FreeOnTerminate;
TSnapThread();
virtual ~TSnapThread();
virtual void Execute() {
};
void Start();
void Terminate();
void Kill();
void Join();
longword WaitFor(uint64_t Timeout);
};
typedef TSnapThread *PSnapThread;
//---------------------------------------------------------------------------
#endif // sol_threads_h
+228
View File
@@ -0,0 +1,228 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|==============================================================================|
| |
| Posix Threads support (Linux, FreeBSD) |
| |
|=============================================================================*/
#ifndef unix_threads_h
#define unix_threads_h
//---------------------------------------------------------------------------
#include "snap_platform.h"
#include "snap_sysutils.h"
#include <semaphore.h>
#include <pthread.h>
//---------------------------------------------------------------------------
class TSnapCriticalSection
{
private:
pthread_mutex_t mx;
// int result;
public:
TSnapCriticalSection()
{
/*
This would be the best code, but very often it causes a segmentation fault in many
unix systems (the problem seems to be pthread_mutexattr_destroy()).
So, to avoid problems in future kernel/libc release, we use the "safe" default.
pthread_mutexattr_t mxAttr;
pthread_mutexattr_settype(&mxAttr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&mx, &mxAttr);
pthread_mutexattr_destroy(&mxAttr);
*/
pthread_mutex_init(&mx, 0);
};
~TSnapCriticalSection()
{
pthread_mutex_destroy(&mx);
};
void Enter()
{
pthread_mutex_lock(&mx);
};
void Leave()
{
pthread_mutex_unlock(&mx);
};
bool TryEnter()
{
return pthread_mutex_trylock(&mx) == 0;
};
};
typedef TSnapCriticalSection *PSnapCriticalSection;
//---------------------------------------------------------------------------
const longword WAIT_OBJECT_0 = 0x00000000L;
const longword WAIT_ABANDONED = 0x00000080L;
const longword WAIT_TIMEOUT = 0x00000102L;
const longword WAIT_FAILED = 0xFFFFFFFFL;
class TSnapEvent
{
private:
pthread_cond_t CVariable;
pthread_mutex_t Mutex;
bool AutoReset;
bool State;
public:
TSnapEvent(bool ManualReset)
{
AutoReset = !ManualReset;
if (pthread_cond_init(&CVariable, 0) == 0)
pthread_mutex_init(&Mutex, 0);
State = false;
}
~TSnapEvent()
{
pthread_cond_destroy(&CVariable);
pthread_mutex_destroy(&Mutex);
};
void Set()
{
pthread_mutex_lock(&Mutex);
State = true;
if (AutoReset)
pthread_cond_signal(&CVariable);
else
pthread_cond_broadcast(&CVariable);
pthread_mutex_unlock(&Mutex);
};
void Reset()
{
pthread_mutex_lock(&Mutex);
State = false;
pthread_mutex_unlock(&Mutex);
}
longword WaitForever()
{
pthread_mutex_lock(&Mutex);
while (!State) // <-- to avoid spurious wakeups
pthread_cond_wait(&CVariable, &Mutex);
if (AutoReset)
State = false;
pthread_mutex_unlock(&Mutex);
return WAIT_OBJECT_0;
};
longword WaitFor(int64_t Timeout)
{
longword Result = WAIT_OBJECT_0;
if (Timeout == 0)
Timeout = 1; // 0 is not allowed
if (Timeout > 0)
{
pthread_mutex_lock(&Mutex);
if (!State)
{
timespec ts;
timeval tv;
gettimeofday(&tv, NULL);
uint64_t nsecs = ((uint64_t) tv.tv_sec) * 1000000000 +
Timeout * 1000000 +
((uint64_t) tv.tv_usec) * 1000;
ts.tv_sec = nsecs / 1000000000;
ts.tv_nsec = (nsecs - ((uint64_t) ts.tv_sec) * 1000000000);
do {
Result = pthread_cond_timedwait(&CVariable, &Mutex, &ts);
if (Result == ETIMEDOUT)
Result = WAIT_TIMEOUT;
} while (Result == 0 && !State);
}
else
if (AutoReset) // take the ownership
State = false;
pthread_mutex_unlock(&Mutex);
return Result;
}
else // Timeout<0
return WaitForever();
};
};
typedef TSnapEvent *PSnapEvent;
//---------------------------------------------------------------------------
class TSnapThread
{
private:
pthread_t th;
bool FCreateSuspended;
void ThreadCreate();
void ThreadJoin()
{
pthread_join(th, 0);
};
void ThreadKill()
{
pthread_cancel(th);
};
longword ThreadWait(uint64_t Timeout)
{
longword Elapsed = SysGetTick();
while (!Closed && !(DeltaTime(Elapsed) > Timeout))
SysSleep(100);
if (Closed)
return WAIT_OBJECT_0;
else
return WAIT_TIMEOUT;
};
protected:
bool Started;
public:
bool Terminated;
bool Closed;
bool FreeOnTerminate;
TSnapThread();
virtual ~TSnapThread();
virtual void Execute()
{
};
void Start();
void Terminate();
void Kill();
void Join();
longword WaitFor(uint64_t Timeout);
};
typedef TSnapThread *PSnapThread;
//---------------------------------------------------------------------------
#endif // unix_threads_h
+159
View File
@@ -0,0 +1,159 @@
/*=============================================================================|
| PROJECT SNAP7 1.3.0 |
|==============================================================================|
| Copyright (C) 2013, 2015 Davide Nardella |
| All rights reserved. |
|==============================================================================|
| SNAP7 is free software: you can redistribute it and/or modify |
| it under the terms of the Lesser GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| It means that you can distribute your commercial software linked with |
| SNAP7 without the requirement to distribute the source code of your |
| application and without the requirement that your application be itself |
| distributed under LGPL. |
| |
| SNAP7 is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Lesser GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License and a |
| copy of Lesser GNU General Public License along with Snap7. |
| If not, see http://www.gnu.org/licenses/ |
|==============================================================================|
| |
| Windows Threads support (Windows, ReactOS) |
| |
|=============================================================================*/
#ifndef win_threads_h
#define win_threads_h
//---------------------------------------------------------------------------
#include "snap_platform.h"
#include "snap_sysutils.h"
//---------------------------------------------------------------------------
class TSnapCriticalSection
{
private:
CRITICAL_SECTION cs;
public:
TSnapCriticalSection()
{
InitializeCriticalSection(&cs);
};
~TSnapCriticalSection()
{
DeleteCriticalSection(&cs);
};
void Enter()
{
EnterCriticalSection(&cs);
};
void Leave()
{
LeaveCriticalSection(&cs);
};
bool TryEnter()
{
return (TryEnterCriticalSection(&cs) != 0);
};
};
typedef TSnapCriticalSection *PSnapCriticalSection;
//---------------------------------------------------------------------------
class TSnapEvent
{
private:
HANDLE Event;
public:
TSnapEvent(bool ManualReset)
{
Event = CreateEvent(0, ManualReset, false, 0);
};
~TSnapEvent()
{
if (Event != 0)
CloseHandle(Event);
};
void Set()
{
if (Event != 0)
SetEvent(Event);
};
void Reset()
{
if (Event != 0)
ResetEvent(Event);
};
longword WaitForever()
{
if (Event != 0)
return WaitForSingleObject(Event, INFINITE);
else
return WAIT_FAILED;
};
longword WaitFor(int64_t Timeout) {
if (Event != 0)
return WaitForSingleObject(Event, DWORD(Timeout));
else
return WAIT_FAILED;
};
};
typedef TSnapEvent *PSnapEvent;
//---------------------------------------------------------------------------
class TSnapThread {
private:
HANDLE th;
bool FCreateSuspended;
void ThreadCreate();
void ThreadJoin()
{
WaitForSingleObject(th, INFINITE);
};
void ThreadKill()
{
TerminateThread(th, 0);
};
longword ThreadWait(uint64_t Timeout)
{
return WaitForSingleObject(th, DWORD(Timeout));
};
protected:
bool Started;
public:
bool Terminated;
bool Closed;
bool FreeOnTerminate;
TSnapThread();
virtual ~TSnapThread();
virtual void Execute()
{
};
void Start();
void Terminate();
void Kill();
void Join();
longword WaitFor(uint64_t Timeout);
};
typedef TSnapThread *PSnapThread;
//---------------------------------------------------------------------------
#endif // win_threads_h
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+15 -1
View File
@@ -37,6 +37,10 @@
#include "ethercat_src.h"
#endif
#ifdef _snap7
#include "oplc_snap7.h"
#endif
#define OPLC_CYCLE 50000000
extern int opterr;
@@ -103,6 +107,7 @@ int main(int argc,char **argv)
#endif
initializeHardware();
initializeMB();
updateBuffersIn();
updateBuffersOut();
@@ -114,7 +119,11 @@ int main(int argc,char **argv)
readPersistentStorage();
//pthread_t persistentThread;
//pthread_create(&persistentThread, NULL, persistentStorage, NULL);
#ifdef _snap7
initializeSnap7();
#endif
#ifdef __linux__
@@ -243,6 +252,11 @@ int main(int argc,char **argv)
#ifdef _ethercat_src
ethercat_terminate_src();
#endif
#ifdef _snap7
finalizeSnap7();
#endif
printf("Disabling outputs\n");
disableOutputs();
updateBuffersOut();
+3 -3
View File
@@ -138,7 +138,7 @@ void mapUnusedIO()
for (int i = 0; i <= MAX_16B_RANGE; i++)
{
if (i < MIN_16B_RANGE)
if (i < MIN_16B_RANGE)
{
if (int_output[i] == NULL)
{
@@ -339,7 +339,7 @@ void ReadHoldingRegisters(unsigned char *buffer, int bufferSize)
for(int i = 0; i < WordDataLength; i++)
{
int position = Start + i;
if (position <= MIN_16B_RANGE)
if (position < MIN_16B_RANGE)
{
if (int_output[position] != NULL)
{
@@ -575,7 +575,7 @@ void WriteCoil(unsigned char *buffer, int bufferSize)
int writeToRegisterWithoutLocking(int position, uint16_t value)
{
//analog outputs
if (position <= MIN_16B_RANGE)
if (position < MIN_16B_RANGE)
{
if (int_output[position] != NULL) *int_output[position] = value;
}
+38 -16
View File
@@ -10,6 +10,7 @@ cd scripts &>/dev/null
OPENPLC_PLATFORM=$(cat openplc_platform)
ETHERCAT_OPT=$(cat ethercat)
OPENPLC_DRIVER=$(cat openplc_driver)
S7_OPT=$(cat s7protocol)
#store the active program filename
echo "$1" > ../active_program
@@ -29,6 +30,27 @@ if [ "$ETHERCAT_OPT" = "ethercat" ]; then
sed -i '7s/^/#include "ethercat_src.h" /' Res0.c
fi
#check for S7 Protocol option
if [ "$S7_OPT" = "s7protocol" ]; then
S7_LIB="-lsnap7"
S7_DEF="-D _snap7"
S7_WLIB="snap7.lib"
cp -f ../utils/snap7_src/wrapper/oplc_snap7.* ./core
if [ "$OPENPLC_PLATFORM" = "win" ]; then
cp -f ../utils/snap7_src/build/bin/win64/snap7.* ./core
fi
echo "Including Siemens S7 Protocol via snap7"
else
S7_LIB=""
S7_DEF=""
S7_WLIB=""
# remove snap7 references (if any)
rm -f ./core/oplc_snap7.*
if [ "$OPENPLC_PLATFORM" = "win" ]; then
rm -f ./core/snap7.*
fi
fi
echo "Moving Files..."
mv -f POUS.c POUS.h LOCATED_VARIABLES.h VARIABLES.csv Config0.c Config0.h Res0.c ./core/
if [ $? -ne 0 ]; then
@@ -64,7 +86,7 @@ if [ "$OPENPLC_PLATFORM" = "win" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
g++ *.cpp *.o -o openplc -I ./lib -pthread -fpermissive -I /usr/local/include/modbus -L /usr/local/lib -lmodbus -w
g++ *.cpp *.o -o openplc -I ./lib -pthread -fpermissive -I /usr/local/include/modbus -L /usr/local/lib $S7_WLIB -lmodbus -w $S7_DEF
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
@@ -77,9 +99,9 @@ elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
echo "Compiling for Linux"
echo "Generating object files..."
if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSL_RP4
g++ -std=gnu++11 -I ./lib -c Config0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSL_RP4
else
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -std=gnu++11 -I ./lib -c Config0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
@@ -87,9 +109,9 @@ elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
exit 1
fi
if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC -DSL_RP4
g++ -std=gnu++11 -I ./lib -c Res0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC $S7_DEF -DSL_RP4
else
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
g++ -std=gnu++11 -I ./lib -c Res0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC $S7_DEF
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
@@ -100,9 +122,9 @@ elif [ "$OPENPLC_PLATFORM" = "linux" ]; then
./glue_generator
echo "Compiling main program..."
if [ "$OPENPLC_DRIVER" = "sl_rp4" ]; then
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC -DSL_RP4
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC $S7_DEF -DSL_RP4
else
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -pthread -fpermissive `pkg-config --cflags --libs libmodbus` $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $ETHERCAT_INC $S7_DEF
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
@@ -116,9 +138,9 @@ elif [ "$OPENPLC_PLATFORM" = "rpi" ]; then
echo "Compiling for Raspberry Pi"
echo "Generating object files..."
if [ "$OPENPLC_DRIVER" = "sequent" ]; then
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSEQUENT
g++ -std=gnu++11 -I ./lib -c Config0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSEQUENT
else
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -std=gnu++11 -I ./lib -c Config0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
@@ -126,9 +148,9 @@ elif [ "$OPENPLC_PLATFORM" = "rpi" ]; then
exit 1
fi
if [ "$OPENPLC_DRIVER" = "sequent" ]; then
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSEQUENT
g++ -std=gnu++11 -I ./lib -c Res0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w -DSEQUENT
else
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -std=gnu++11 -I ./lib -c Res0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
@@ -139,9 +161,9 @@ elif [ "$OPENPLC_PLATFORM" = "rpi" ]; then
./glue_generator
echo "Compiling main program..."
if [ "$OPENPLC_DRIVER" = "sequent" ]; then
g++ -DSEQUENT -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lpigpio -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -DSEQUENT -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lpigpio -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal $S7_DEF -w
else
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lpigpio -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lpigpio -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal $S7_DEF -w
fi
if [ $? -ne 0 ]; then
echo "Error compiling C files"
@@ -155,13 +177,13 @@ elif [ "$OPENPLC_PLATFORM" = "opi" ]; then
WIRINGOP_INC="-I/usr/local/include -L/usr/local/lib -lwiringPi -lwiringPiDev"
echo "Compiling for Orange Pi"
echo "Generating object files..."
g++ -std=gnu++11 -I ./lib -c Config0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $WIRINGOP_INC
g++ -std=gnu++11 -I ./lib -c Config0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $WIRINGOP_INC
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
exit 1
fi
g++ -std=gnu++11 -I ./lib -c Res0.c -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $WIRINGOP_INC
g++ -std=gnu++11 -I ./lib -c Res0.c $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $WIRINGOP_INC
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
@@ -170,7 +192,7 @@ elif [ "$OPENPLC_PLATFORM" = "opi" ]; then
echo "Generating glueVars..."
./glue_generator
echo "Compiling main program..."
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $WIRINGOP_INC
g++ -std=gnu++11 *.cpp *.o -o openplc -I ./lib -lrt -lpthread -fpermissive `pkg-config --cflags --libs libmodbus` $S7_LIB -lasiodnp3 -lasiopal -lopendnp3 -lopenpal -w $S7_DEF $WIRINGOP_INC
if [ $? -ne 0 ]; then
echo "Error compiling C files"
echo "Compilation finished with errors!"
+1
View File
@@ -0,0 +1 @@
#s7protocol