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