All Downloads are FREE. Search and download functionalities are using the official Maven repository.

HslCommunication.Profinet.Omron.OmronHostLinkOverTcp Maven / Gradle / Ivy

Go to download

一个工业物联网的底层架构框架,专注于底层的技术通信及跨平台,跨语言通信功能,实现各种主流的PLC数据读写,实现modbus的各种协议读写等等

There is a newer version: 3.7.0
Show newest version
package HslCommunication.Profinet.Omron;

import HslCommunication.BasicFramework.SoftBasic;
import HslCommunication.Core.IMessage.INetMessage;
import HslCommunication.Core.Net.NetworkBase.NetworkDeviceBase;
import HslCommunication.Core.Transfer.DataFormat;
import HslCommunication.Core.Transfer.ReverseWordTransform;
import HslCommunication.Core.Types.*;
import HslCommunication.StringResources;
import HslCommunication.Utilities;

import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.logging.Level;

public class OmronHostLinkOverTcp extends NetworkDeviceBase {

    public OmronHostLinkOverTcp( )
    {
        this.setByteTransform(new ReverseWordTransform( ));
        this.WordLength               = 1;
        this.getByteTransform().setDataFormat(DataFormat.CDAB);
        //this.getByteTransform().setIsStringReverse(true);
    }

    public OmronHostLinkOverTcp( String ipAddress, int port )
    {
        this();
        this.setIpAddress(ipAddress);
        this.setPort(port);
    }

    protected OperateResultExOne UnpackResponseContent( byte[] send, byte[] response )
    {
        return ResponseValidAnalysis( send, response );
    }

    /// 
    /// Specifies whether or not there are network relays. Set “80” (ASCII: 38,30)
    /// when sending an FINS command to a CPU Unit on a network.Set “00” (ASCII: 30,30)
    /// when sending to a CPU Unit connected directly to the host computer.
    /// 
    public byte ICF = 0x00;

    /// 
    public byte DA2 = 0x00;

    /// 
    public byte SA2 = 0x00;

    /// 
    public byte SID  = 0x00;

    /**
     * The response wait time sets the time from when the CPU Unit receives a command block until it starts
     * to return a response.It can be set from 0 to F in hexadecimal, in units of 10 ms.
     * If F(15) is set, the response will begin to be returned 150 ms (15 × 10 ms) after the command block was received.
     */
    public byte ResponseWaitTime = 0x30;

    /**
     * PLC设备的站号信息
* PLC device station number information */ public byte UnitNumber = 0; /** * 进行字读取的时候对于超长的情况按照本属性进行切割,默认260。
* When reading words, it is cut according to this attribute for the case of overlength. The default is 260. */ public int ReadSplits = 260; protected OperateResultExOne ReceiveByMessage(Socket socket, int timeOut, INetMessage netMessage, ActionOperateExTwo reportProgress ) { return ReceiveCommandLineFromSocket( socket, (byte) 0x0D, timeOut ); } public OperateResultExOne Read( String address, short length ) { byte station = this.UnitNumber; OperateResultExTwo analysis = HslHelper.ExtractParameter(address, "s", this.UnitNumber); if (analysis.IsSuccess) { station = analysis.Content1.byteValue(); address = analysis.Content2; } // 解析地址 OperateResultExOne command = OmronFinsNetHelper.BuildReadCommand(address, length, false, ReadSplits); //ReadSplits if (!command.IsSuccess) return OperateResultExOne.CreateFailedResult(command); ArrayList contentArray = new ArrayList<>(); for (int i = 0; i < command.Content.length; i++) { // 核心交互 OperateResultExOne read = ReadFromCoreServer(PackCommand(station, command.Content[i])); if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult(read); // 读取到了正确的数据 Utilities.ArrayListAddArray(contentArray, read.Content); } return OperateResultExOne.CreateSuccessResult(Utilities.ToByteArray(contentArray)); } public OperateResult Write(String address, byte[] value ) { byte station = this.UnitNumber; OperateResultExTwo analysis = HslHelper.ExtractParameter(address, "s", this.UnitNumber); if(analysis.IsSuccess){ station = analysis.Content1.byteValue(); address = analysis.Content2; } // 获取指令 OperateResultExOne command = OmronFinsNetHelper.BuildWriteWordCommand( address, value, false ); ; if (!command.IsSuccess) return command; // 核心数据交互 OperateResultExOne read = ReadFromCoreServer( PackCommand( station, command.Content ) ); if (!read.IsSuccess) return read; // 成功 return OperateResult.CreateSuccessResult( ); } public OperateResultExOne ReadBool( String address, short length ) { byte station = this.UnitNumber; OperateResultExTwo analysis = HslHelper.ExtractParameter(address, "s", this.UnitNumber); if (analysis.IsSuccess) { station = analysis.Content1.byteValue(); address = analysis.Content2; } // 获取指令 OperateResultExOne command = OmronFinsNetHelper.BuildReadCommand(address, length, true, ReadSplits); if (!command.IsSuccess) return OperateResultExOne.CreateFailedResult(command); ArrayList contentArray = new ArrayList(); for (int i = 0; i < command.Content.length; i++) { // 核心交互 OperateResultExOne read = ReadFromCoreServer(PackCommand(station, command.Content[i])); if (!read.IsSuccess) return OperateResultExOne.CreateFailedResult(read); // 返回正确的数据信息 if (read.Content.length == 0) return new OperateResultExOne("Data is empty."); for (int j = 0; j < read.Content.length; j++) { contentArray.add(read.Content[j] != 0x00); } } return OperateResultExOne.CreateSuccessResult(Utilities.getBools(contentArray)); } public OperateResult Write( String address, boolean[] values ) { byte station = this.UnitNumber; OperateResultExTwo analysis = HslHelper.ExtractParameter(address, "s", this.UnitNumber); if (analysis.IsSuccess) { station = analysis.Content1.byteValue(); address = analysis.Content2; } // 获取指令 OperateResultExOne command = OmronFinsNetHelper.BuildWriteWordCommand(address, TransBoolsArray(values), true); ; if (!command.IsSuccess) return command; // 核心数据交互 OperateResultExOne read = ReadFromCoreServer(PackCommand(station, command.Content)); if (!read.IsSuccess) return read; // 成功 return OperateResult.CreateSuccessResult(); } public String toString( ) { return "OmronHostLinkOverTcp[" + getIpAddress() + ":" + getPort() + "]"; } /** * 将普通的指令打包成完整的指令 * @param station PLC的站号信息 * @param cmd fins指令 * @return 完整的质量 */ private byte[] PackCommand( byte station, byte[] cmd ) { cmd = SoftBasic.BytesToAsciiBytes(cmd); byte[] buffer = new byte[18 + cmd.length]; buffer[ 0] = (byte) '@'; buffer[ 1] = SoftBasic.BuildAsciiBytesFrom(station)[0]; buffer[ 2] = SoftBasic.BuildAsciiBytesFrom(station)[1]; buffer[ 3] = (byte) 'F'; buffer[ 4] = (byte) 'A'; buffer[ 5] = ResponseWaitTime; buffer[ 6] = SoftBasic.BuildAsciiBytesFrom(this.ICF)[0]; buffer[ 7] = SoftBasic.BuildAsciiBytesFrom(this.ICF)[1]; buffer[ 8] = SoftBasic.BuildAsciiBytesFrom(this.DA2)[0]; buffer[ 9] = SoftBasic.BuildAsciiBytesFrom(this.DA2)[1]; buffer[10] = SoftBasic.BuildAsciiBytesFrom(this.SA2)[0]; buffer[11] = SoftBasic.BuildAsciiBytesFrom(this.SA2)[1]; buffer[12] = SoftBasic.BuildAsciiBytesFrom(this.SID)[0]; buffer[13] = SoftBasic.BuildAsciiBytesFrom(this.SID)[1]; buffer[buffer.length - 2] = (byte) '*'; buffer[buffer.length - 1] = 0x0D; System.arraycopy(cmd, 0, buffer, 14, cmd.length); // 计算FCS int tmp = buffer[0]; for (int i = 1; i < buffer.length - 4; i++) { tmp ^= buffer[i]; } buffer[buffer.length - 4] = SoftBasic.BuildAsciiBytesFrom((byte) tmp)[0]; buffer[buffer.length - 3] = SoftBasic.BuildAsciiBytesFrom((byte) tmp)[1]; return buffer; } /** * 验证欧姆龙的Fins-TCP返回的数据是否正确的数据,如果正确的话,并返回所有的数据内容 * @param send 发送的报文信息 * @param response 来自欧姆龙返回的数据内容 * @return 带有是否成功的结果对象 */ public static OperateResultExOne ResponseValidAnalysis(byte[] send, byte[] response ) { // 数据有效性分析 // @00FA00400000000102000040*\cr if (response.length >= 27) { String commandSend = new String(send, 14, 4, StandardCharsets.US_ASCII); String commandReceive = new String(response, 15, 4, StandardCharsets.US_ASCII); if (!commandReceive.equals(commandSend)) return new OperateResultExOne("Send Command [" + commandSend + "] not the same as receive command [" + commandReceive + "]"); // 提取错误码 int err = Integer.parseInt(new String(response, 19, 4, StandardCharsets.US_ASCII), 16); byte[] content = new byte[0]; if (response.length > 27) content = SoftBasic.HexStringToBytes(new String(response, 23, response.length - 27, StandardCharsets.US_ASCII)); if (err > 0) { OperateResultExOne result = new OperateResultExOne(); result.ErrorCode = err; result.Content = content; result.Message = GetErrorText(err); } else return OperateResultExOne.CreateSuccessResult(content); } return new OperateResultExOne(StringResources.Language.OmronReceiveDataError() + " Source Data: " + SoftBasic.ByteToHexString(response, ' ')); } /** * 根据错误信息获取当前的文本描述信息 * @param error 错误代号 * @return 文本消息 */ public static String GetErrorText( int error ) { switch (error) { case 0x0001: return "Service was canceled."; case 0x0101: return "Local node is not participating in the network."; case 0x0102: return "Token does not arrive."; case 0x0103: return "Send was not possible during the specified number of retries."; case 0x0104: return "Cannot send because maximum number of event frames exceeded."; case 0x0105: return "Node address setting error occurred."; case 0x0106: return "The same node address has been set twice in the same network."; case 0x0201: return "The destination node is not in the network."; case 0x0202: return "There is no Unit with the specified unit address."; case 0x0203: return "The third node does not exist."; case 0x0204: return "The destination node is busy."; case 0x0205: return "The message was destroyed by noise"; case 0x0301: return "An error occurred in the communications controller."; case 0x0302: return "A CPU error occurred in the destination CPU Unit."; case 0x0303: return "A response was not returned because an error occurred in the Board."; case 0x0304: return "The unit number was set incorrectly"; case 0x0401: return "The Unit/Board does not support the specified command code."; case 0x0402: return "The command cannot be executed because the model or version is incorrect"; case 0x0501: return "The destination network or node address is not set in the routing tables."; case 0x0502: return "Relaying is not possible because there are no routing tables"; case 0x0503: return "There is an error in the routing tables."; case 0x0504: return "An attempt was made to send to a network that was over 3 networks away"; // Command format error case 0x1001: return "The command is longer than the maximum permissible length."; case 0x1002: return "The command is shorter than the minimum permissible length."; case 0x1003: return "The designated number of elements differs from the number of write data items."; case 0x1004: return "An incorrect format was used."; case 0x1005: return "Either the relay table in the local node or the local network table in the relay node is incorrect."; // Parameter error case 0x1101: return "The specified word does not exist in the memory area or there is no EM Area."; case 0x1102: return "The access size specification is incorrect or an odd word address is specified."; case 0x1103: return "The start address in command process is beyond the accessible area"; case 0x1104: return "The end address in command process is beyond the accessible area."; case 0x1106: return "FFFF hex was not specified."; case 0x1109: return "A large–small relationship in the elements in the command data is incorrect."; case 0x110B: return "The response format is longer than the maximum permissible length."; case 0x110C: return "There is an error in one of the parameter settings."; // Read Not Possible case 0x2002: return "The program area is protected."; case 0x2003: return "A table has not been registered."; case 0x2004: return "The search data does not exist."; case 0x2005: return "A non-existing program number has been specified."; case 0x2006: return "The file does not exist at the specified file device."; case 0x2007: return "A data being compared is not the same."; // Write not possible case 0x2101: return "The specified area is read-only."; case 0x2102: return "The program area is protected."; case 0x2103: return "The file cannot be created because the limit has been exceeded."; case 0x2105: return "A non-existing program number has been specified."; case 0x2106: return "The file does not exist at the specified file device."; case 0x2107: return "A file with the same name already exists in the specified file device."; case 0x2108: return "The change cannot be made because doing so would create a problem."; // Not executable in current mode case 0x2201: case 0x2202: case 0x2208: return "The mode is incorrect."; case 0x2203: return "The PLC is in PROGRAM mode."; case 0x2204: return "The PLC is in DEBUG mode."; case 0x2205: return "The PLC is in MONITOR mode."; case 0x2206: return "The PLC is in RUN mode."; case 0x2207: return "The specified node is not the polling node."; // No such device case 0x2301: return "The specified memory does not exist as a file device."; case 0x2302: return "There is no file memory."; case 0x2303: return "There is no clock."; case 0x2401: return "The data link tables have not been registered or they contain an error."; default: return StringResources.Language.UnknownError(); } } public static byte[] TransBoolsArray(boolean[] values){ byte[] buffer = new byte[values.length]; for (int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy