/* * Copyright (c) 2016, Mathias Küsel * MIT License */ #include #include #include namespace node_snap7 { Nan::Persistent S7Client::constructor; NAN_MODULE_INIT(S7Client::Init) { Nan::HandleScope scope; v8::Local tpl; tpl = Nan::New(S7Client::New); v8::Local name = Nan::New("S7Client") .ToLocalChecked(); tpl->SetClassName(name); tpl->InstanceTemplate()->SetInternalFieldCount(1); // Setup the prototype // Control functions Nan::SetPrototypeMethod( tpl , "Connect" , S7Client::Connect); Nan::SetPrototypeMethod( tpl , "ConnectTo" , S7Client::ConnectTo); Nan::SetPrototypeMethod( tpl , "SetConnectionParams" , S7Client::SetConnectionParams); Nan::SetPrototypeMethod( tpl , "SetConnectionType" , S7Client::SetConnectionType); Nan::SetPrototypeMethod( tpl , "Disconnect" , S7Client::Disconnect); Nan::SetPrototypeMethod( tpl , "GetParam" , S7Client::GetParam); Nan::SetPrototypeMethod( tpl , "SetParam" , S7Client::SetParam); // Data I/O Main functions Nan::SetPrototypeMethod( tpl , "ReadArea" , S7Client::ReadArea); Nan::SetPrototypeMethod( tpl , "WriteArea" , S7Client::WriteArea); Nan::SetPrototypeMethod( tpl , "ReadMultiVars" , S7Client::ReadMultiVars); Nan::SetPrototypeMethod( tpl , "WriteMultiVars" , S7Client::WriteMultiVars); // Directory functions Nan::SetPrototypeMethod( tpl , "ListBlocks" , S7Client::ListBlocks); Nan::SetPrototypeMethod( tpl , "GetAgBlockInfo" , S7Client::GetAgBlockInfo); Nan::SetPrototypeMethod( tpl , "GetPgBlockInfo" , S7Client::GetPgBlockInfo); Nan::SetPrototypeMethod( tpl , "ListBlocksOfType" , S7Client::ListBlocksOfType); // Blocks functions Nan::SetPrototypeMethod( tpl , "Upload" , S7Client::Upload); Nan::SetPrototypeMethod( tpl , "FullUpload" , S7Client::FullUpload); Nan::SetPrototypeMethod( tpl , "Download" , S7Client::Download); Nan::SetPrototypeMethod( tpl , "Delete" , S7Client::Delete); Nan::SetPrototypeMethod( tpl , "DBGet" , S7Client::DBGet); Nan::SetPrototypeMethod( tpl , "DBFill" , S7Client::DBFill); // Date/Time functions Nan::SetPrototypeMethod( tpl , "GetPlcDateTime" , S7Client::GetPlcDateTime); Nan::SetPrototypeMethod( tpl , "SetPlcDateTime" , S7Client::SetPlcDateTime); Nan::SetPrototypeMethod( tpl , "SetPlcSystemDateTime" , S7Client::SetPlcSystemDateTime); // System Info functions Nan::SetPrototypeMethod( tpl , "GetOrderCode" , S7Client::GetOrderCode); Nan::SetPrototypeMethod( tpl , "GetCpuInfo" , S7Client::GetCpuInfo); Nan::SetPrototypeMethod( tpl , "GetCpInfo" , S7Client::GetCpInfo); Nan::SetPrototypeMethod( tpl , "ReadSZL" , S7Client::ReadSZL); Nan::SetPrototypeMethod( tpl , "ReadSZLList" , S7Client::ReadSZLList); // Control functions Nan::SetPrototypeMethod( tpl , "PlcHotStart" , S7Client::PlcHotStart); Nan::SetPrototypeMethod( tpl , "PlcColdStart" , S7Client::PlcColdStart); Nan::SetPrototypeMethod( tpl , "PlcStop" , S7Client::PlcStop); Nan::SetPrototypeMethod( tpl , "CopyRamToRom" , S7Client::CopyRamToRom); Nan::SetPrototypeMethod( tpl , "Compress" , S7Client::Compress); // Security functions Nan::SetPrototypeMethod( tpl , "GetProtection" , S7Client::GetProtection); Nan::SetPrototypeMethod( tpl , "SetSessionPassword" , S7Client::SetSessionPassword); Nan::SetPrototypeMethod( tpl , "ClearSessionPassword" , S7Client::ClearSessionPassword); // Properties Nan::SetPrototypeMethod( tpl , "ExecTime" , S7Client::ExecTime); Nan::SetPrototypeMethod( tpl , "LastError" , S7Client::LastError); Nan::SetPrototypeMethod( tpl , "PDURequested" , S7Client::PDURequested); Nan::SetPrototypeMethod( tpl , "PDULength" , S7Client::PDULength); Nan::SetPrototypeMethod( tpl , "PlcStatus" , S7Client::PlcStatus); Nan::SetPrototypeMethod( tpl , "Connected" , S7Client::Connected); // Error to text function Nan::SetPrototypeMethod( tpl , "ErrorText" , S7Client::ErrorText); // Error codes Nan::SetPrototypeTemplate( tpl , Nan::New("errNegotiatingPDU").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidParams").ToLocalChecked() , Nan::New(errCliInvalidParams) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliJobPending").ToLocalChecked() , Nan::New(errCliJobPending) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliTooManyItems").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidWordLen").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliPartialDataWritten").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliSizeOverPDU").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidPlcAnswer").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliAddressOutOfRange").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidTransportSize").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliWriteDataSizeMismatch").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliItemNotAvailable").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidValue").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliCannotStartPLC").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliAlreadyRun").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliCannotStopPLC").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliCannotCopyRamToRom").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliCannotCompress").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliAlreadyStop").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliFunNotAvailable").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliUploadSequenceFailed").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidDataSizeRecvd").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidBlockType").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidBlockNumber").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidBlockSize").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliDownloadSequenceFailed").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInsertRefused").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliDeleteRefused").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliNeedPassword").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidPassword").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliNoPasswordToSetOrClear").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliJobTimeout").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliPartialDataRead").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliBufferTooSmall").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliFunctionRefused").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliDestroying").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliInvalidParamNumber").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("errCliCannotChangeParam").ToLocalChecked() , Nan::New(errNegotiatingPDU) , v8::ReadOnly); // Client Connection Type Nan::SetPrototypeTemplate( tpl , Nan::New("CONNTYPE_PG").ToLocalChecked() , Nan::New(CONNTYPE_PG) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("CONNTYPE_OP").ToLocalChecked() , Nan::New(CONNTYPE_OP) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("CONNTYPE_BASIC").ToLocalChecked() , Nan::New(CONNTYPE_BASIC) , v8::ReadOnly); // CPU Status codes Nan::SetPrototypeTemplate( tpl , Nan::New("S7CpuStatusUnknown").ToLocalChecked() , Nan::New(S7CpuStatusUnknown) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7CpuStatusRun").ToLocalChecked() , Nan::New(S7CpuStatusRun) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7CpuStatusStop").ToLocalChecked() , Nan::New(S7CpuStatusStop) , v8::ReadOnly); // Area ID Nan::SetPrototypeTemplate( tpl , Nan::New("S7AreaPE").ToLocalChecked() , Nan::New(S7AreaPE) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7AreaPA").ToLocalChecked() , Nan::New(S7AreaPA) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7AreaMK").ToLocalChecked() , Nan::New(S7AreaMK) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7AreaDB").ToLocalChecked() , Nan::New(S7AreaDB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7AreaCT").ToLocalChecked() , Nan::New(S7AreaCT) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7AreaTM").ToLocalChecked() , Nan::New(S7AreaTM) , v8::ReadOnly); // Word Length Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLBit").ToLocalChecked() , Nan::New(S7WLBit) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLByte").ToLocalChecked() , Nan::New(S7WLByte) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLWord").ToLocalChecked() , Nan::New(S7WLWord) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLDWord").ToLocalChecked() , Nan::New(S7WLDWord) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLReal").ToLocalChecked() , Nan::New(S7WLReal) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLCounter").ToLocalChecked() , Nan::New(S7WLCounter) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("S7WLTimer").ToLocalChecked() , Nan::New(S7WLTimer) , v8::ReadOnly); // Block type Nan::SetPrototypeTemplate( tpl , Nan::New("Block_OB").ToLocalChecked() , Nan::New(Block_OB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("Block_DB").ToLocalChecked() , Nan::New(Block_DB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("Block_SDB").ToLocalChecked() , Nan::New(Block_SDB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("Block_FC").ToLocalChecked() , Nan::New(Block_FC) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("Block_SFC").ToLocalChecked() , Nan::New(Block_SFC) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("Block_FB").ToLocalChecked() , Nan::New(Block_FB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("Block_SFB").ToLocalChecked() , Nan::New(Block_SFB) , v8::ReadOnly); // Sub Block Type Nan::SetPrototypeTemplate( tpl , Nan::New("SubBlk_OB").ToLocalChecked() , Nan::New(SubBlk_OB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SubBlk_SDB").ToLocalChecked() , Nan::New(SubBlk_SDB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SubBlk_FC").ToLocalChecked() , Nan::New(SubBlk_FC) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SubBlk_SFC").ToLocalChecked() , Nan::New(SubBlk_SFC) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SubBlk_FB").ToLocalChecked() , Nan::New(SubBlk_FB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SubBlk_SFB").ToLocalChecked() , Nan::New(SubBlk_SFB) , v8::ReadOnly); // Block languages Nan::SetPrototypeTemplate( tpl , Nan::New("BlockLangAWL").ToLocalChecked() , Nan::New(BlockLangAWL) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BlockLangKOP").ToLocalChecked() , Nan::New(BlockLangKOP) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BlockLangFUP").ToLocalChecked() , Nan::New(BlockLangFUP) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BlockLangSCL").ToLocalChecked() , Nan::New(BlockLangSCL) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BlockLangDB").ToLocalChecked() , Nan::New(BlockLangDB) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BlockLangGRAPH").ToLocalChecked() , Nan::New(BlockLangGRAPH) , v8::ReadOnly); // Parameter Nan::SetPrototypeTemplate( tpl , Nan::New("LocalPort").ToLocalChecked() , Nan::New(p_u16_LocalPort) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("RemotePort").ToLocalChecked() , Nan::New(p_u16_RemotePort) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("PingTimeout").ToLocalChecked() , Nan::New(p_i32_PingTimeout) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SendTimeout").ToLocalChecked() , Nan::New(p_i32_SendTimeout) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("RecvTimeout").ToLocalChecked() , Nan::New(p_i32_RecvTimeout) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("WorkInterval").ToLocalChecked() , Nan::New(p_i32_WorkInterval) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SrcRef").ToLocalChecked() , Nan::New(p_u16_SrcRef) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("DstRef").ToLocalChecked() , Nan::New(p_u16_DstRef) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("SrcTSap").ToLocalChecked() , Nan::New(p_u16_SrcTSap) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("PDURequest").ToLocalChecked() , Nan::New(p_i32_PDURequest) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("MaxClients").ToLocalChecked() , Nan::New(p_i32_MaxClients) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BSendTimeout").ToLocalChecked() , Nan::New(p_i32_BSendTimeout) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("BRecvTimeout").ToLocalChecked() , Nan::New(p_i32_BRecvTimeout) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("RecoveryTime").ToLocalChecked() , Nan::New(p_u32_RecoveryTime) , v8::ReadOnly); Nan::SetPrototypeTemplate( tpl , Nan::New("KeepAliveTime").ToLocalChecked() , Nan::New(p_u32_KeepAliveTime) , v8::ReadOnly); constructor.Reset(tpl); Nan::Set(target, name, tpl->GetFunction()); } NAN_METHOD(S7Client::New) { if (info.IsConstructCall()) { S7Client *s7client = new S7Client(); s7client->Wrap(info.This()); info.GetReturnValue().Set(info.This()); } else { v8::Local constructorHandle; constructorHandle = Nan::New(constructor); info.GetReturnValue().Set(constructorHandle->GetFunction()->NewInstance()); } } S7Client::S7Client() { snap7Client = new TS7Client(); uv_mutex_init(&mutex); } S7Client::~S7Client() { snap7Client->Disconnect(); delete snap7Client; constructor.Reset(); uv_mutex_destroy(&mutex); } int S7Client::GetByteCountFromWordLen(int WordLen) { switch (WordLen) { case S7WLBit: case S7WLByte: return 1; case S7WLWord: case S7WLCounter: case S7WLTimer: return 2; case S7WLReal: case S7WLDWord: return 4; default: return 0; } } void S7Client::FreeCallback(char *data, void *hint) { delete[] data; } void S7Client::FreeCallbackSZL(char *data, void *hint) { delete reinterpret_cast(data); } // Control functions NAN_METHOD(S7Client::Connect) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { int ret = s7client->snap7Client->Connect(); info.GetReturnValue().Set(Nan::New(ret == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, CONNECT)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::ConnectTo) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (info.Length() < 3) { return Nan::ThrowTypeError("Wrong number of arguments"); } if (!info[0]->IsString() || !info[1]->IsInt32() || !info[2]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } Nan::Utf8String *remAddress = new Nan::Utf8String(info[0]); if (!info[3]->IsFunction()) { int ret = s7client->snap7Client->ConnectTo( **remAddress , info[1]->Int32Value() , info[2]->Int32Value()); delete remAddress; info.GetReturnValue().Set(Nan::New(ret == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[3].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, CONNECTTO , remAddress, info[1]->Int32Value(), info[2]->Int32Value())); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::SetConnectionParams) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsString() || !info[1]->IsUint32() || !info[2]->IsUint32()) { return Nan::ThrowTypeError("Wrong arguments"); } Nan::Utf8String remAddress(info[0]); word LocalTSAP = info[1]->Uint32Value(); word RemoteTSAP = info[2]->Uint32Value(); int ret = s7client->snap7Client->SetConnectionParams( *remAddress , LocalTSAP , RemoteTSAP); info.GetReturnValue().Set(Nan::New(ret == 0)); } NAN_METHOD(S7Client::SetConnectionType) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsUint32()) { return Nan::ThrowTypeError("Wrong arguments"); } word type = info[0]->Uint32Value(); int ret = s7client->snap7Client->SetConnectionType(type); info.GetReturnValue().Set(Nan::New(ret == 0)); } NAN_METHOD(S7Client::Disconnect) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); int ret = s7client->snap7Client->Disconnect(); info.GetReturnValue().Set(Nan::New(ret == 0)); } NAN_METHOD(S7Client::GetParam) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } int pData; int returnValue = s7client->snap7Client->GetParam(info[0]->Int32Value() , &pData); if (returnValue == 0) { info.GetReturnValue().Set(Nan::New(pData)); } else { info.GetReturnValue().Set(Nan::New(returnValue)); } } NAN_METHOD(S7Client::SetParam) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!(info[0]->IsInt32() || info[1]->IsInt32())) { return Nan::ThrowTypeError("Wrong arguments"); } int pData = info[1]->Int32Value(); int ret = s7client->snap7Client->SetParam(info[0]->Int32Value(), &pData); info.GetReturnValue().Set(Nan::New(ret == 0)); } // Data I/O Main functions void IOWorker::Execute() { uv_mutex_lock(&s7client->mutex); switch (caller) { case CONNECTTO: returnValue = s7client->snap7Client->ConnectTo( **static_cast(pData), int1, int2); break; case CONNECT: returnValue = s7client->snap7Client->Connect(); break; case READAREA: returnValue = s7client->snap7Client->ReadArea(int1, int2, int3, int4 , int5, pData); break; case WRITEAREA: returnValue = s7client->snap7Client->WriteArea(int1, int2, int3, int4 , int5, pData); break; case READMULTI: returnValue = s7client->snap7Client->ReadMultiVars( static_cast(pData), int1); break; case WRITEMULTI: returnValue = s7client->snap7Client->WriteMultiVars( static_cast(pData), int1); break; case PLCSTATUS: returnValue = s7client->snap7Client->PlcStatus(); if ((returnValue == S7CpuStatusUnknown) || (returnValue == S7CpuStatusStop) || (returnValue == S7CpuStatusRun)) { int1 = returnValue; returnValue = 0; } break; case CLEARSESSIONPW: returnValue = s7client->snap7Client->ClearSessionPassword(); break; case SETSESSIONPW: returnValue = s7client->snap7Client->SetSessionPassword( **static_cast(pData)); break; case GETPROTECTION: returnValue = s7client->snap7Client->GetProtection( static_cast(pData)); break; case PLCSTOP: returnValue = s7client->snap7Client->PlcStop(); break; case PLCCOLDSTART: returnValue = s7client->snap7Client->PlcColdStart(); break; case PLCHOTSTART: returnValue = s7client->snap7Client->PlcHotStart(); break; case GETCPINFO: returnValue = s7client->snap7Client->GetCpInfo( static_cast(pData)); break; case GETCPUINFO: returnValue = s7client->snap7Client->GetCpuInfo( static_cast(pData)); break; case GETORDERCODE: returnValue = s7client->snap7Client->GetOrderCode( static_cast(pData)); break; case SETPLCSYSTEMDATETIME: returnValue = s7client->snap7Client->SetPlcSystemDateTime(); break; case GETPLCDATETIME: returnValue = s7client->snap7Client->GetPlcDateTime( static_cast(pData)); break; case SETPLCDATETIME: returnValue = s7client->snap7Client->SetPlcDateTime( static_cast(pData)); break; case COMPRESS: returnValue = s7client->snap7Client->Compress(int1); break; case COPYRAMTOROM: returnValue = s7client->snap7Client->CopyRamToRom(int1); break; case DBFILL: returnValue = s7client->snap7Client->DBFill(int1, int2); break; case DBGET: returnValue = s7client->snap7Client->DBGet(int1, pData, &int2); break; case DELETEBLOCK: returnValue = s7client->snap7Client->Delete(int1, int2); break; case DOWNLOAD: returnValue = s7client->snap7Client->Download(int1, pData, int2); break; case FULLUPLOAD: returnValue = s7client->snap7Client->FullUpload(int1, int2, pData, &int3); break; case UPLOAD: returnValue = s7client->snap7Client->Upload(int1, int2, pData, &int3); break; case LISTBLOCKSOFTYPE: returnValue = s7client->snap7Client->ListBlocksOfType(int1 , static_cast(pData), &int2); break; case GETAGBLOCKINFO: returnValue = s7client->snap7Client->GetAgBlockInfo(int1, int2 , static_cast(pData)); break; case LISTBLOCKS: returnValue = s7client->snap7Client->ListBlocks( static_cast(pData)); break; case READSZLLIST: returnValue = s7client->snap7Client->ReadSZLList( static_cast(pData), &int1); break; case READSZL: returnValue = s7client->snap7Client->ReadSZL(int1, int2 , static_cast(pData), &int3); break; } uv_mutex_unlock(&s7client->mutex); } void IOWorker::HandleOKCallback() { Nan::HandleScope scope; v8::Local argv1[1]; v8::Local argv2[2]; if (returnValue == 0) { argv2[0] = argv1[0] = Nan::Null(); } else { argv2[0] = argv1[0] = Nan::New(returnValue); } switch (caller) { case CONNECTTO: case SETSESSIONPW: delete static_cast(pData); callback->Call(1, argv1); break; case CONNECT: case WRITEAREA: case CLEARSESSIONPW: case PLCSTOP: case PLCCOLDSTART: case PLCHOTSTART: case SETPLCSYSTEMDATETIME: case COPYRAMTOROM: case COMPRESS: case DBFILL: case DELETEBLOCK: case DOWNLOAD: callback->Call(1, argv1); break; case READAREA: if (returnValue == 0) { argv2[1] = Nan::NewBuffer( static_cast(pData) , int4 * s7client->GetByteCountFromWordLen(int5) , S7Client::FreeCallback, NULL).ToLocalChecked(); } else { argv2[1] = Nan::Null(); delete[] static_cast(pData); } callback->Call(2, argv2); break; case READMULTI: if (returnValue == 0) { argv2[1] = s7client->S7DataItemToArray(static_cast(pData) , int1, true); } else { for (int i = 0; i < int1; i++) { delete[] static_cast(static_cast(pData)[i].pdata); } delete[] static_cast(pData); argv2[1] = Nan::Null(); } callback->Call(2, argv2); break; case WRITEMULTI: if (returnValue == 0) { argv2[1] = s7client->S7DataItemToArray(static_cast(pData) , int1, false); } else { delete[] static_cast(pData); argv2[1] = Nan::Null(); } callback->Call(2, argv2); break; case GETPROTECTION: if (returnValue == 0) { argv2[1] = s7client->S7ProtectionToObject( static_cast(pData)); } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case GETCPINFO: if (returnValue == 0) { argv2[1] = s7client->S7CpInfoToObject( static_cast(pData)); } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case GETCPUINFO: if (returnValue == 0) { argv2[1] = s7client->S7CpuInfoToObject( static_cast(pData)); } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case GETORDERCODE: if (returnValue == 0) { argv2[1] = s7client->S7OrderCodeToObject( static_cast(pData)); } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case GETPLCDATETIME: if (returnValue == 0) { double timestamp = static_cast(mktime(static_cast(pData))); argv2[1] = Nan::New(timestamp * 1000).ToLocalChecked(); } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case SETPLCDATETIME: delete static_cast(pData); callback->Call(1, argv1); break; case PLCSTATUS: if (returnValue == 0) { argv2[1] = Nan::New(int1); } else { argv2[1] = Nan::Null(); } callback->Call(2, argv2); break; case DBGET: if (returnValue == 0) { argv2[1] = Nan::NewBuffer( static_cast(pData) , int2 , S7Client::FreeCallback , NULL).ToLocalChecked(); } else { argv2[1] = Nan::Null(); delete[] static_cast(pData); } callback->Call(2, argv2); break; case FULLUPLOAD: case UPLOAD: if (returnValue == 0) { argv2[1] = Nan::NewBuffer( static_cast(pData) , int3 , S7Client::FreeCallback , NULL).ToLocalChecked(); } else { argv2[1] = Nan::Null(); delete[] static_cast(pData); } callback->Call(2, argv2); break; case LISTBLOCKSOFTYPE: if (returnValue == 0) { argv2[1] = s7client->S7BlocksOfTypeToArray( static_cast(pData), int2); } else { argv2[1] = Nan::Null(); } delete[] static_cast(pData); callback->Call(2, argv2); break; case GETAGBLOCKINFO: if (returnValue == 0) { v8::Local block_info = s7client->S7BlockInfoToObject( static_cast(pData)); argv2[1] = block_info; } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case LISTBLOCKS: if (returnValue == 0) { v8::Local blocks_list = s7client->S7BlocksListToObject( static_cast(pData)); argv2[1] = blocks_list; } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case READSZLLIST: if (returnValue == 0) { v8::Local szl_list = s7client->S7SZLListToArray( static_cast(pData), int1); argv2[1] = szl_list; } else { argv2[1] = Nan::Null(); } delete static_cast(pData); callback->Call(2, argv2); break; case READSZL: if (returnValue == 0) { argv2[1] = Nan::NewBuffer( reinterpret_cast(static_cast(pData)) , int3 , S7Client::FreeCallbackSZL , NULL).ToLocalChecked(); } else { argv2[1] = Nan::Null(); delete static_cast(pData); } callback->Call(2, argv2); break; } } NAN_METHOD(S7Client::ReadArea) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (info.Length() < 5) return Nan::ThrowTypeError("Wrong number of Arguments"); if (!info[0]->IsInt32() || !info[1]->IsInt32() || !info[2]->IsInt32() || !info[3]->IsInt32() || !info[4]->IsInt32()) return Nan::ThrowTypeError("Wrong arguments"); int amount = info[3]->Int32Value(); int byteCount = s7client->GetByteCountFromWordLen(info[4]->Int32Value()); int size = amount * byteCount; char *bufferData = new char[size]; if (!info[5]->IsFunction()) { int returnValue = s7client->snap7Client->ReadArea( info[0]->Int32Value(), info[1]->Int32Value() , info[2]->Int32Value(), info[3]->Int32Value() , info[4]->Int32Value(), bufferData); if (returnValue == 0) { v8::Local ret = Nan::NewBuffer( bufferData , size , S7Client::FreeCallback , NULL).ToLocalChecked(); info.GetReturnValue().Set(ret); } else { delete[] bufferData; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[5].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READAREA , bufferData, info[0]->Int32Value(), info[1]->Int32Value() , info[2]->Int32Value(), info[3]->Int32Value(), info[4]->Int32Value())); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::WriteArea) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (info.Length() < 6) return Nan::ThrowTypeError("Wrong number of Arguments"); if (!info[0]->IsInt32() || !info[1]->IsInt32() || !info[2]->IsInt32() || !info[3]->IsInt32() || !info[4]->IsInt32() || !node::Buffer::HasInstance(info[5])) return Nan::ThrowTypeError("Wrong arguments"); if (!info[6]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->WriteArea(info[0]->Int32Value() , info[1]->Int32Value(), info[2]->Int32Value() , info[3]->Int32Value(), info[4]->Int32Value() , node::Buffer::Data(info[5].As())) == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[6].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, WRITEAREA , node::Buffer::Data(info[5].As()), info[0]->Int32Value() , info[1]->Int32Value(), info[2]->Int32Value(), info[3]->Int32Value() , info[4]->Int32Value())); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::ReadMultiVars) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (info.Length() < 1) { return Nan::ThrowTypeError("Wrong number of arguments"); } if (!info[0]->IsArray()) { return Nan::ThrowTypeError("Wrong arguments"); } v8::Local data_arr = v8::Local::Cast(info[0]); int len = data_arr->Length(); if (len == 0) { return Nan::ThrowTypeError("Array needs at least 1 item"); } else if (len > MaxVars) { std::stringstream err; err << "Array exceeds max variables (" << MaxVars << ") that can be transferred with ReadMultiVars()"; return Nan::ThrowTypeError(err.str().c_str()); } for (int i = 0; i < len; i++) { if (!Nan::Get(data_arr, i).ToLocalChecked()->IsObject()) { return Nan::ThrowTypeError("Wrong argument structure"); } else { v8::Local data_obj = Nan::Get(data_arr, i).ToLocalChecked()->ToObject(); if (!Nan::Has(data_obj, Nan::New("Area").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("WordLen").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("Start").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("Amount").ToLocalChecked()).FromJust()) { return Nan::ThrowTypeError("Wrong argument structure"); } else if (!Nan::Get(data_obj, Nan::New("Area").ToLocalChecked()).ToLocalChecked()->IsInt32() || !Nan::Get(data_obj, Nan::New("WordLen").ToLocalChecked()).ToLocalChecked()->IsInt32() || !Nan::Get(data_obj, Nan::New("Start").ToLocalChecked()).ToLocalChecked()->IsInt32() || !Nan::Get(data_obj, Nan::New("Amount").ToLocalChecked()).ToLocalChecked()->IsInt32()) { return Nan::ThrowTypeError("Wrong argument structure"); } else if (Nan::Get(data_obj, Nan::New("Area").ToLocalChecked()).ToLocalChecked()->Int32Value() == S7AreaDB) { if (!Nan::Has(data_obj, Nan::New("DBNumber").ToLocalChecked()).FromJust()) { return Nan::ThrowTypeError("Wrong argument structure"); } } else { Nan::Set(data_obj, Nan::New("DBNumber").ToLocalChecked(), Nan::New(0)); } } } PS7DataItem Items = new TS7DataItem[len]; v8::Local data_obj; int byteCount, size; for (int i = 0; i < len; i++) { data_obj = Nan::Get(data_arr, i).ToLocalChecked()->ToObject(); Items[i].Area = Nan::Get(data_obj, Nan::New("Area").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].WordLen = Nan::Get(data_obj, Nan::New("WordLen").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].DBNumber = Nan::Get(data_obj, Nan::New("DBNumber").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].Start = Nan::Get(data_obj, Nan::New("Start").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].Amount = Nan::Get(data_obj, Nan::New("Amount").ToLocalChecked()).ToLocalChecked()->Int32Value(); byteCount = s7client->GetByteCountFromWordLen(Items[i].WordLen); size = Items[i].Amount * byteCount; Items[i].pdata = new char[size]; } if (!info[1]->IsFunction()) { int returnValue = s7client->snap7Client->ReadMultiVars(Items, len); if (returnValue == 0) { info.GetReturnValue().Set(s7client->S7DataItemToArray(Items, len, true)); } else { for (int i = 0; i < len; i++) { delete[] static_cast(Items[i].pdata); } delete[] Items; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READMULTI , Items, len)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7DataItemToArray( PS7DataItem Items , int len , bool readMulti ) { Nan::EscapableHandleScope scope; v8::Local res_arr = Nan::New(len); v8::Local res_obj; int byteCount, size; for (int i = 0; i < len; i++) { res_obj = Nan::New(); Nan::Set(res_obj, Nan::New("Result").ToLocalChecked() , Nan::New(Items[i].Result)); if (readMulti == true) { if (Items[i].Result == 0) { byteCount = S7Client::GetByteCountFromWordLen(Items[i].WordLen); size = byteCount * Items[i].Amount; Nan::Set( res_obj , Nan::New("Data").ToLocalChecked() , Nan::NewBuffer( static_cast(Items[i].pdata) , size , S7Client::FreeCallback , NULL).ToLocalChecked()); } else { delete[] static_cast(Items[i].pdata); Nan::Set(res_obj, Nan::New("Data").ToLocalChecked(), Nan::Null()); } } Nan::Set(res_arr, i, res_obj); } delete[] Items; return scope.Escape(res_arr); } NAN_METHOD(S7Client::WriteMultiVars) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (info.Length() < 1) { return Nan::ThrowTypeError("Wrong number of arguments"); } if (!info[0]->IsArray()) { return Nan::ThrowTypeError("Wrong arguments"); } v8::Local data_arr = v8::Local::Cast(info[0]); int len = data_arr->Length(); if (len == 0) { return Nan::ThrowTypeError("Array needs at least 1 item"); } else if (len > MaxVars) { std::stringstream err; err << "Array exceeds max variables (" << MaxVars << ") that can be transferred with WriteMultiVars()"; return Nan::ThrowTypeError(err.str().c_str()); } for (int i = 0; i < len; i++) { if (!Nan::Get(data_arr, i).ToLocalChecked()->IsObject()) { return Nan::ThrowTypeError("Wrong argument structure"); } else { v8::Local data_obj = Nan::Get(data_arr, i).ToLocalChecked()->ToObject(); if (!Nan::Has(data_obj, Nan::New("Area").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("WordLen").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("Start").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("Amount").ToLocalChecked()).FromJust() || !Nan::Has(data_obj, Nan::New("Data").ToLocalChecked()).FromJust()) { return Nan::ThrowTypeError("Wrong argument structure"); } else if (!Nan::Get(data_obj, Nan::New("Area").ToLocalChecked()).ToLocalChecked()->IsInt32() || !Nan::Get(data_obj, Nan::New("WordLen").ToLocalChecked()).ToLocalChecked()->IsInt32() || !Nan::Get(data_obj, Nan::New("Start").ToLocalChecked()).ToLocalChecked()->IsInt32() || !Nan::Get(data_obj, Nan::New("Amount").ToLocalChecked()).ToLocalChecked()->IsInt32() || !node::Buffer::HasInstance(Nan::Get(data_obj, Nan::New("Data").ToLocalChecked()).ToLocalChecked())) { return Nan::ThrowTypeError("Wrong argument structure"); } else if (Nan::Get(data_obj, Nan::New("Area").ToLocalChecked()).ToLocalChecked()->Int32Value() == S7AreaDB) { if (!Nan::Has(data_obj, Nan::New("DBNumber").ToLocalChecked()).FromJust()) { return Nan::ThrowTypeError("Wrong argument structure"); } } else { Nan::Set(data_obj, Nan::New("DBNumber").ToLocalChecked(), Nan::New(0)); } } } PS7DataItem Items = new TS7DataItem[len]; v8::Local data_obj; for (int i = 0; i < len; i++) { data_obj = Nan::Get(data_arr, i).ToLocalChecked()->ToObject(); Items[i].Area = Nan::Get(data_obj, Nan::New("Area").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].WordLen = Nan::Get(data_obj, Nan::New("WordLen").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].DBNumber = Nan::Get(data_obj, Nan::New("DBNumber").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].Start = Nan::Get(data_obj, Nan::New("Start").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].Amount = Nan::Get(data_obj, Nan::New("Amount").ToLocalChecked()).ToLocalChecked()->Int32Value(); Items[i].pdata = node::Buffer::Data(Nan::Get(data_obj, Nan::New("Data").ToLocalChecked()).ToLocalChecked().As()); } if (!info[1]->IsFunction()) { int returnValue = s7client->snap7Client->WriteMultiVars(Items, len); if (returnValue == 0) { info.GetReturnValue().Set(s7client->S7DataItemToArray(Items, len, false)); } else { delete[] Items; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, WRITEMULTI , Items, len)); info.GetReturnValue().SetUndefined(); } } // Directory functions NAN_METHOD(S7Client::ListBlocks) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); PS7BlocksList BlocksList = new TS7BlocksList; if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->ListBlocks(BlocksList); v8::Local blocks_list = s7client->S7BlocksListToObject( BlocksList); if (returnValue == 0) { delete BlocksList; info.GetReturnValue().Set(blocks_list); } else { delete BlocksList; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, LISTBLOCKS , BlocksList)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7BlocksListToObject( PS7BlocksList BlocksList ) { Nan::EscapableHandleScope scope; v8::Local blocks_list = Nan::New(); Nan::Set(blocks_list, Nan::New("OBCount").ToLocalChecked() , Nan::New(BlocksList->OBCount)); Nan::Set(blocks_list, Nan::New("FBCount").ToLocalChecked() , Nan::New(BlocksList->FBCount)); Nan::Set(blocks_list, Nan::New("FCCount").ToLocalChecked() , Nan::New(BlocksList->FCCount)); Nan::Set(blocks_list, Nan::New("SFBCount").ToLocalChecked() , Nan::New(BlocksList->SFBCount)); Nan::Set(blocks_list, Nan::New("SFCCount").ToLocalChecked() , Nan::New(BlocksList->SFCCount)); Nan::Set(blocks_list, Nan::New("DBCount").ToLocalChecked() , Nan::New(BlocksList->DBCount)); Nan::Set(blocks_list, Nan::New("SDBCount").ToLocalChecked() , Nan::New(BlocksList->SDBCount)); return scope.Escape(blocks_list); } NAN_METHOD(S7Client::GetAgBlockInfo) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !info[1]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } PS7BlockInfo BlockInfo = new TS7BlockInfo; if (!info[2]->IsFunction()) { int returnValue = s7client->snap7Client->GetAgBlockInfo( info[0]->Int32Value(), info[1]->Int32Value(), BlockInfo); if (returnValue == 0) { v8::Local block_info = s7client->S7BlockInfoToObject( BlockInfo); delete BlockInfo; info.GetReturnValue().Set(block_info); } else { delete BlockInfo; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[2].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETAGBLOCKINFO , BlockInfo, info[0]->Int32Value(), info[1]->Int32Value())); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::GetPgBlockInfo) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!node::Buffer::HasInstance(info[0])) { return Nan::ThrowTypeError("Argument should be a Buffer"); } PS7BlockInfo BlockInfo = new TS7BlockInfo; int returnValue = s7client->snap7Client->GetPgBlockInfo( node::Buffer::Data(info[0].As()), BlockInfo , static_cast(node::Buffer::Length(info[0].As()))); if (returnValue == 0) { v8::Local block_info = s7client->S7BlockInfoToObject(BlockInfo); delete BlockInfo; info.GetReturnValue().Set(block_info); } else { delete BlockInfo; info.GetReturnValue().Set(Nan::False()); } } v8::Local S7Client::S7BlockInfoToObject(PS7BlockInfo BlockInfo) { Nan::EscapableHandleScope scope; v8::Local block_info = Nan::New(); Nan::Set(block_info, Nan::New("BlkType").ToLocalChecked() , Nan::New(BlockInfo->BlkType)); Nan::Set(block_info, Nan::New("BlkNumber").ToLocalChecked() , Nan::New(BlockInfo->BlkNumber)); Nan::Set(block_info, Nan::New("BlkLang").ToLocalChecked() , Nan::New(BlockInfo->BlkLang)); Nan::Set(block_info, Nan::New("BlkFlags").ToLocalChecked() , Nan::New(BlockInfo->BlkFlags)); Nan::Set(block_info, Nan::New("MC7Size").ToLocalChecked() , Nan::New(BlockInfo->MC7Size)); Nan::Set(block_info, Nan::New("LoadSize").ToLocalChecked() , Nan::New(BlockInfo->LoadSize)); Nan::Set(block_info, Nan::New("LocalData").ToLocalChecked() , Nan::New(BlockInfo->LocalData)); Nan::Set(block_info, Nan::New("SBBLength").ToLocalChecked() , Nan::New(BlockInfo->SBBLength)); Nan::Set(block_info, Nan::New("CheckSum").ToLocalChecked() , Nan::New(BlockInfo->CheckSum)); Nan::Set(block_info, Nan::New("Version").ToLocalChecked() , Nan::New(BlockInfo->Version)); Nan::Set(block_info, Nan::New("CodeDate").ToLocalChecked() , Nan::New(BlockInfo->CodeDate).ToLocalChecked()); Nan::Set(block_info, Nan::New("IntfDate").ToLocalChecked() , Nan::New(BlockInfo->IntfDate).ToLocalChecked()); Nan::Set(block_info, Nan::New("Author").ToLocalChecked() , Nan::New(BlockInfo->Author).ToLocalChecked()); Nan::Set(block_info, Nan::New("Family").ToLocalChecked() , Nan::New(BlockInfo->Family).ToLocalChecked()); Nan::Set(block_info, Nan::New("Header").ToLocalChecked() , Nan::New(BlockInfo->Header).ToLocalChecked()); return scope.Escape(block_info); } NAN_METHOD(S7Client::ListBlocksOfType) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } int BlockNum = sizeof(TS7BlocksOfType) / sizeof(PS7BlocksOfType); PS7BlocksOfType BlockList = new TS7BlocksOfType[BlockNum]; if (!info[1]->IsFunction()) { int returnValue = s7client->snap7Client->ListBlocksOfType( info[0]->Int32Value(), BlockList, &BlockNum); if (returnValue == 0) { v8::Local block_list = s7client->S7BlocksOfTypeToArray( BlockList, BlockNum); delete[] BlockList; info.GetReturnValue().Set(block_list); } else { delete[] BlockList; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, LISTBLOCKSOFTYPE , BlockList, info[0]->Int32Value(), BlockNum)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7BlocksOfTypeToArray( PS7BlocksOfType BlocksList , int count ) { Nan::EscapableHandleScope scope; v8::Local block_list = Nan::New(count); for (int i = 0; i < count; i++) { Nan::Set(block_list, i, Nan::New(*BlocksList[i])); } return scope.Escape(block_list); } // Blocks functions NAN_METHOD(S7Client::Upload) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !info[1]->IsInt32() || !info[2]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } char *bufferData = new char[info[2]->Int32Value()]; int size = info[2]->Int32Value(); if (!info[3]->IsFunction()) { int returnValue = s7client->snap7Client->Upload( info[0]->Int32Value(), info[1]->Int32Value(), bufferData, &size); if (returnValue == 0) { v8::Local ret_buf; ret_buf = Nan::NewBuffer( bufferData , size , S7Client::FreeCallback , NULL).ToLocalChecked(); info.GetReturnValue().Set(ret_buf); } else { delete[] bufferData; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[3].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, UPLOAD , bufferData, info[0]->Int32Value(), info[1]->Int32Value(), size)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::FullUpload) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !info[1]->IsInt32() || !info[2]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } char *bufferData = new char[info[2]->Int32Value()]; int size = info[2]->Int32Value(); if (!info[3]->IsFunction()) { int returnValue = s7client->snap7Client->FullUpload( info[0]->Int32Value(), info[1]->Int32Value(), bufferData, &size); if (returnValue == 0) { v8::Local ret_buf; ret_buf = Nan::NewBuffer( bufferData , size , S7Client::FreeCallback , NULL).ToLocalChecked(); info.GetReturnValue().Set(ret_buf); } else { delete[] bufferData; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[3].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, FULLUPLOAD , bufferData, info[0]->Int32Value(), info[1]->Int32Value(), size)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::Download) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !node::Buffer::HasInstance(info[1])) { return Nan::ThrowTypeError("Wrong arguments"); } if (!info[2]->IsFunction()) { info.GetReturnValue().Set(Nan::New(s7client->snap7Client->Download( info[0]->Int32Value(), node::Buffer::Data(info[1].As()) , static_cast(node::Buffer::Length(info[1].As()))) == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[2].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DOWNLOAD , node::Buffer::Data(info[1].As()), info[0]->Int32Value() , static_cast(node::Buffer::Length(info[1].As())))); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::Delete) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !info[1]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } if (!info[2]->IsFunction()) { info.GetReturnValue().Set(Nan::New(s7client->snap7Client->Delete( info[0]->Int32Value(), info[1]->Int32Value()) == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[2].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DELETEBLOCK , info[0]->Int32Value(), info[1]->Int32Value())); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::DBGet) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !info[1]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } int size = info[1]->Int32Value(); char *bufferData = new char[size]; if (!info[2]->IsFunction()) { int returnValue = s7client->snap7Client->DBGet( info[0]->Int32Value(), bufferData, &size); if (returnValue == 0) { v8::Local ret_buf; ret_buf = Nan::NewBuffer( bufferData , size , S7Client::FreeCallback , NULL).ToLocalChecked(); info.GetReturnValue().Set(ret_buf); } else { delete[] bufferData; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[2].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DBGET , bufferData, info[0]->Int32Value(), size)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::DBFill) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32() || !(info[1]->IsInt32() || info[1]->IsString())) { return Nan::ThrowTypeError("Wrong arguments"); } int fill; if (info[1]->IsInt32()) { fill = info[1]->Int32Value(); } else { Nan::Utf8String fillstr(info[1]); fill = static_cast(**fillstr); } if (!info[2]->IsFunction()) { info.GetReturnValue().Set(Nan::New(s7client->snap7Client->DBFill( info[0]->Int32Value(), fill) == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[2].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, DBFILL , info[0]->Int32Value(), fill)); info.GetReturnValue().SetUndefined(); } } // Date/Time functions NAN_METHOD(S7Client::GetPlcDateTime) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); tm *DateTime = new tm; if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->GetPlcDateTime(DateTime); double timestamp = static_cast(mktime(DateTime)); delete DateTime; if (returnValue == 0) info.GetReturnValue().Set(Nan::New(timestamp * 1000).ToLocalChecked()); else info.GetReturnValue().Set(Nan::False()); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETPLCDATETIME , DateTime)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::SetPlcDateTime) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!(info[0]->IsObject() || info[0]->IsDate())) { return Nan::ThrowTypeError("Wrong arguments"); } tm *DateTime = new tm; if (info[0]->IsDate()) { v8::Local date = v8::Local::Cast(info[0]->ToObject()); time_t timestamp = static_cast(date->NumberValue() / 1000); *DateTime = *localtime(×tamp); } else { v8::Local date_time = info[0]->ToObject(); DateTime->tm_year = Nan::Get(date_time, Nan::New("year").ToLocalChecked()).ToLocalChecked()->Int32Value() - 1900; DateTime->tm_mon = Nan::Get(date_time, Nan::New("month").ToLocalChecked()).ToLocalChecked()->Int32Value(); DateTime->tm_mday = Nan::Get(date_time, Nan::New("day").ToLocalChecked()).ToLocalChecked()->Int32Value(); DateTime->tm_hour = Nan::Get(date_time, Nan::New("hours").ToLocalChecked()).ToLocalChecked()->Int32Value(); DateTime->tm_min = Nan::Get(date_time, Nan::New("minutes").ToLocalChecked()).ToLocalChecked()->Int32Value(); DateTime->tm_sec = Nan::Get(date_time, Nan::New("seconds").ToLocalChecked()).ToLocalChecked()->Int32Value(); } if (!info[1]->IsFunction()) { v8::Local ret = Nan::New( s7client->snap7Client->SetPlcDateTime(DateTime) == 0); delete DateTime; info.GetReturnValue().Set(ret); } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, SETPLCDATETIME , DateTime)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::SetPlcSystemDateTime) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->SetPlcSystemDateTime() == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, SETPLCSYSTEMDATETIME)); info.GetReturnValue().SetUndefined(); } } // System Info functions NAN_METHOD(S7Client::GetOrderCode) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); PS7OrderCode OrderCode = new TS7OrderCode; if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->GetOrderCode(OrderCode); if (returnValue == 0) { v8::Local order_code = s7client->S7OrderCodeToObject(OrderCode); delete OrderCode; info.GetReturnValue().Set(order_code); } else { delete OrderCode; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETORDERCODE , OrderCode)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7OrderCodeToObject(PS7OrderCode OrderCode) { Nan::EscapableHandleScope scope; v8::Local order_code = Nan::New(); Nan::Set(order_code, Nan::New("Code").ToLocalChecked() , Nan::New(OrderCode->Code).ToLocalChecked()); Nan::Set(order_code, Nan::New("V1").ToLocalChecked() , Nan::New(OrderCode->V1)); Nan::Set(order_code, Nan::New("V2").ToLocalChecked() , Nan::New(OrderCode->V2)); Nan::Set(order_code, Nan::New("V3").ToLocalChecked() , Nan::New(OrderCode->V3)); return scope.Escape(order_code); } NAN_METHOD(S7Client::GetCpuInfo) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); PS7CpuInfo CpuInfo = new TS7CpuInfo; if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->GetCpuInfo(CpuInfo); if (returnValue == 0) { v8::Local cpu_info = s7client->S7CpuInfoToObject(CpuInfo); delete CpuInfo; info.GetReturnValue().Set(cpu_info); } else { delete CpuInfo; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETCPUINFO, CpuInfo)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7CpuInfoToObject(PS7CpuInfo CpuInfo) { Nan::EscapableHandleScope scope; v8::Local cpu_info = Nan::New(); Nan::Set(cpu_info, Nan::New("ModuleTypeName").ToLocalChecked() , Nan::New(CpuInfo->ModuleTypeName).ToLocalChecked()); Nan::Set(cpu_info, Nan::New("SerialNumber").ToLocalChecked() , Nan::New(CpuInfo->SerialNumber).ToLocalChecked()); Nan::Set(cpu_info, Nan::New("ASName").ToLocalChecked() , Nan::New(CpuInfo->ASName).ToLocalChecked()); Nan::Set(cpu_info, Nan::New("Copyright").ToLocalChecked() , Nan::New(CpuInfo->Copyright).ToLocalChecked()); Nan::Set(cpu_info, Nan::New("ModuleName").ToLocalChecked() , Nan::New(CpuInfo->ModuleName).ToLocalChecked()); return scope.Escape(cpu_info); } NAN_METHOD(S7Client::GetCpInfo) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); PS7CpInfo CpInfo = new TS7CpInfo; if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->GetCpInfo(CpInfo); if (returnValue == 0) { v8::Local cp_info = s7client->S7CpInfoToObject(CpInfo); delete CpInfo; info.GetReturnValue().Set(cp_info); } else { delete CpInfo; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETCPINFO, CpInfo)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7CpInfoToObject(PS7CpInfo CpInfo) { Nan::EscapableHandleScope scope; v8::Local cp_info = Nan::New(); Nan::Set(cp_info, Nan::New("MaxPduLength").ToLocalChecked() , Nan::New(CpInfo->MaxPduLengt)); Nan::Set(cp_info, Nan::New("MaxConnections").ToLocalChecked() , Nan::New(CpInfo->MaxConnections)); Nan::Set(cp_info, Nan::New("MaxMpiRate").ToLocalChecked() , Nan::New(CpInfo->MaxMpiRate)); Nan::Set(cp_info, Nan::New("MaxBusRate").ToLocalChecked() , Nan::New(CpInfo->MaxBusRate)); return scope.Escape(cp_info); } NAN_METHOD(S7Client::ReadSZL) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!(info[0]->IsInt32() || info[1]->IsInt32())) { return Nan::ThrowTypeError("Wrong arguments"); } PS7SZL SZL = new TS7SZL; int size = sizeof(TS7SZL); if (!info[2]->IsFunction()) { int returnValue = s7client->snap7Client->ReadSZL(info[0]->Int32Value() , info[1]->Int32Value(), SZL, &size); if (returnValue == 0) { v8::Local ret_buf; ret_buf = Nan::NewBuffer( reinterpret_cast(SZL) , size , S7Client::FreeCallbackSZL , NULL).ToLocalChecked(); info.GetReturnValue().Set(ret_buf); } else { delete SZL; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[2].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READSZL, SZL , info[0]->Int32Value(), info[1]->Int32Value(), size)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::ReadSZLList) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); PS7SZLList SZLList = new TS7SZLList; int size = sizeof(TS7SZLList); if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->ReadSZLList(SZLList, &size); if (returnValue == 0) { v8::Local szl_list = s7client->S7SZLListToArray(SZLList, size); delete SZLList; info.GetReturnValue().Set(szl_list); } else { delete SZLList; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, READSZLLIST, SZLList , size)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7SZLListToArray(PS7SZLList SZLList, int count) { Nan::EscapableHandleScope scope; v8::Local szl_list = Nan::New(count); for (int i = 0; i < count; i++) { Nan::Set(szl_list, i, Nan::New((*SZLList).List[i])); } return scope.Escape(szl_list); } // Control functions NAN_METHOD(S7Client::PlcHotStart) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->PlcHotStart() == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCHOTSTART)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::PlcColdStart) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->PlcColdStart() == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCCOLDSTART)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::PlcStop) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->PlcStop() == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCSTOP)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::CopyRamToRom) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } if (!info[1]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->CopyRamToRom(info[0]->Int32Value()) == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, COPYRAMTOROM , info[0]->Int32Value())); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::Compress) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } if (!info[1]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->Compress(info[0]->Int32Value()) == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, COMPRESS , info[0]->Int32Value())); info.GetReturnValue().SetUndefined(); } } // Security functions NAN_METHOD(S7Client::GetProtection) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); PS7Protection S7Protection = new TS7Protection; if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->GetProtection(S7Protection); if (returnValue == 0) { v8::Local protection = s7client->S7ProtectionToObject( S7Protection); delete S7Protection; info.GetReturnValue().Set(protection); } else { delete S7Protection; info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, GETPROTECTION , S7Protection)); info.GetReturnValue().SetUndefined(); } } v8::Local S7Client::S7ProtectionToObject( PS7Protection S7Protection ) { Nan::EscapableHandleScope scope; v8::Local protection = Nan::New(); Nan::Set(protection, Nan::New("sch_schal").ToLocalChecked() , Nan::New(S7Protection->sch_schal)); Nan::Set(protection, Nan::New("sch_par").ToLocalChecked() , Nan::New(S7Protection->sch_par)); Nan::Set(protection, Nan::New("sch_rel").ToLocalChecked() , Nan::New(S7Protection->sch_rel)); Nan::Set(protection, Nan::New("bart_sch").ToLocalChecked() , Nan::New(S7Protection->bart_sch)); Nan::Set(protection, Nan::New("anl_sch").ToLocalChecked() , Nan::New(S7Protection->anl_sch)); return scope.Escape(protection); } NAN_METHOD(S7Client::SetSessionPassword) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsString()) { return Nan::ThrowTypeError("Wrong arguments"); } Nan::Utf8String *password = new Nan::Utf8String(info[0]); if (!info[1]->IsFunction()) { v8::Local ret = Nan::New( s7client->snap7Client->SetSessionPassword(**password) == 0); delete password; info.GetReturnValue().Set(ret); } else { Nan::Callback *callback = new Nan::Callback(info[1].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, SETSESSIONPW , password)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::ClearSessionPassword) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { info.GetReturnValue().Set(Nan::New( s7client->snap7Client->ClearSessionPassword() == 0)); } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, CLEARSESSIONPW)); info.GetReturnValue().SetUndefined(); } } // Properties NAN_METHOD(S7Client::ExecTime) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); int returnValue = s7client->snap7Client->ExecTime(); if (returnValue == errLibInvalidObject) { info.GetReturnValue().Set(Nan::False()); } else { info.GetReturnValue().Set(Nan::New(returnValue)); } } NAN_METHOD(S7Client::LastError) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); info.GetReturnValue().Set(Nan::New( s7client->snap7Client->LastError())); } NAN_METHOD(S7Client::PDURequested) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); int returnValue = s7client->snap7Client->PDURequested(); if (returnValue == 0) { info.GetReturnValue().Set(Nan::False()); } else { info.GetReturnValue().Set(Nan::New(returnValue)); } } NAN_METHOD(S7Client::PDULength) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); int returnValue = s7client->snap7Client->PDULength(); if (returnValue == 0) { info.GetReturnValue().Set(Nan::False()); } else { info.GetReturnValue().Set(Nan::New(returnValue)); } } NAN_METHOD(S7Client::PlcStatus) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); if (!info[0]->IsFunction()) { int returnValue = s7client->snap7Client->PlcStatus(); if ((returnValue == S7CpuStatusUnknown) || (returnValue == S7CpuStatusStop) || (returnValue == S7CpuStatusRun)) { info.GetReturnValue().Set(Nan::New(returnValue)); } else { info.GetReturnValue().Set(Nan::False()); } } else { Nan::Callback *callback = new Nan::Callback(info[0].As()); Nan::AsyncQueueWorker(new IOWorker(callback, s7client, PLCSTATUS)); info.GetReturnValue().SetUndefined(); } } NAN_METHOD(S7Client::Connected) { S7Client *s7client = ObjectWrap::Unwrap(info.Holder()); info.GetReturnValue().Set(Nan::New( s7client->snap7Client->Connected())); } NAN_METHOD(S7Client::ErrorText) { if (!info[0]->IsInt32()) { return Nan::ThrowTypeError("Wrong arguments"); } info.GetReturnValue().Set(Nan::New( CliErrorText(info[0]->Int32Value()).c_str()).ToLocalChecked()); } } // namespace node_snap7