/*@!Encoding:1252*/ includes { #include "include\ModbusUdpClientCommon.cin" #include "include\DeviceInformation.cin" } variables { msTimer gtRead; } on preStart { writeClear(0); setStartdelay(10); OutputDebugLevel = Warning; } on start { DeviceInit(@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::Vendor); ModbusInit(); ModbusReadOutBits(gDevOutputBitAddr, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits); ModbusReadOutRegisters(gDevOutputRegAddr, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters); if (@sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval > 0) setTimerCyclic(gtRead, 1, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval); } // Modbus events ---------------------------------------------------------------------- void OnModbusReadBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { word i; switch (error) { case Exception: break; case Timeout: break; case FinalTimeout: sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits"); for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits; i++) @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i] = -1; sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits"); break; } } void OnModbusReadRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { byte i; switch (error) { case Exception: break; case Timeout: break; case FinalTimeout: sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters"); for (i = 0; i < @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters; i++) @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i] = -1; sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters"); break; } } void OnModbusWriteBitFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { } void OnModbusWriteRegisterFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { } void OnModbusWriteMasksFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { } void OnModbusReadWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { } void OnModbusWriteBitsFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { } void OnModbusWriteRegistersFailed(enum ModbusRequestError error, enum ModbusException ex, struct ModbusApHeader mbap) { } void OnModbusReadBitsSuccess(struct ModbusResReceiveBits mbres, byte bitStatus[], struct ModbusReqRead mbreq) { word i, offset; switch (mbres.Header.FuncCode) // We assume that we separate between 0x01 and 0x02 even though the address space may be the same { case 0x01: // Read output bits sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits"); offset = mbreq.Address - gDevOutputBitAddr; // Get the offset to the base output bit address for (i = 0; i < mbreq.Count; i++) @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i + offset] = bitStatus[i]; sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputBits"); break; case 0x02: // Read input bits sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits"); offset = mbreq.Address - gDevInputBitAddr; // Get the offset to the base input bit address for (i = 0; i < mbreq.Count; i++) @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputBits[i + offset] = bitStatus[i]; sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputBits"); break; } } void OnModbusReadRegistersSuccess(struct ModbusResReceiveRegisters mbres, struct ModbusReqRead mbreq) { word i, offset; switch (mbres.Header.FuncCode) // We assume that we separate between 0x03 and 0x04 even though the address space may be the same { case 0x03: // Read output registers sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters"); offset = mbreq.Address - gDevOutputRegAddr; // Get the offset to the base output register address for (i = 0; i < mbreq.Count; i++) @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i + offset] = mbres.Data[i]; sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "OutputRegisters"); break; case 0x04: // Read input registers sysBeginVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters"); offset = mbreq.Address - gDevInputRegAddr; // Get the offset to the base input bit address for (i = 0; i < mbreq.Count; i++) @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::InputRegisters[i + offset] = mbres.Data[i]; sysEndVariableStructUpdate("%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data", "InputRegisters"); break; } } void OnModbusWriteBitSuccess(struct ModbusResConfirmSingle mbc) { } void OnModbusWriteRegisterSuccess(struct ModbusResConfirmSingle mbc) { } void OnModbusWriteBitsSuccess(struct ModbusResConfirmMultiple mbc) { } void OnModbusWriteRegistersSuccess(struct ModbusResConfirmMultiple mbc) { } void OnModbusWriteMasksSuccess(struct ModbusResConfirmMasks mbc) { } void OnModbusClientPanics(enum FatalErrors reason) { writeLineEx(0, 4, "<%NODE_NAME%> FATAL! %d", reason); switch(reason) { case ParsingBuffer: case ModbusPackageWasSplit: case DeviceCodeUnknown: case VendorIdUnknown: runError(1001, reason); break; case ConnectionError: gtRead.Cancel(); break; } } // Key events ------------------------------------------------------------------------- on timer gtRead { ModbusReadRegisters(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputRegisters); ModbusReadBits(0x0000, @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::InputBits); //this.Cancel(); } on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits { word count, i; byte bitStatus[1968]; count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputBits; for (i = 0; i < count; i++) bitStatus[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputBits[i]; ModbusWriteBitsB(0, count, bitStatus); } on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters { word count, i; word regValues[123]; count = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Info::OutputRegisters; for (i = 0; i < count; i++) regValues[i] = @sysvar::%BUS_TYPE%%CHANNEL%::%NODE_NAME%::Data::OutputRegisters[i]; ModbusWriteRegisters(0x000, count, regValues); } on sysvar %BUS_TYPE%%CHANNEL%::%NODE_NAME%::Config::Interval { if (@this <= 0) gtRead.Cancel(); else setTimerCyclic(gtRead, @this); }