//调用前应对地址数组排序(是否加锁?),先一整块PDU读取到 缓存中,然后再逐个从缓存中 读取到各变量地址中
        public static ItemData <Storage>[] PLCReadMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrsArr)
        {
            if (addrsArr == null || cache == null || addrsArr.Length == 0)
            {
                return(null);
            }
            int len = addrsArr.Length;                                 //读取的 变量地址的个数

            ItemData <Storage>[] items = new ItemData <Storage> [len]; //需要填充的列表
            int            offset = 0; long now = DateTime.Now.ToFileTime();
            List <PDUArea> areas = cache.AssignFromPDU(plc.PDU, addrsArr);

            foreach (PDUArea area in areas)
            {
                byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len);
                Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length);
                offset += rcvBytes.Length / cache.ByteCount;
            }
            for (int i = 0; i < len; i++)
            {
                switch (addrsArr[i].VarType)
                {
                case DataType.BOOL:
                    items[i].Value.Boolean = cache.ReadBit(addrsArr[i]).Value;
                    break;

                case DataType.BYTE:
                    items[i].Value.Byte = cache.ReadByte(addrsArr[i]).Value;
                    break;

                case DataType.WORD:
                    items[i].Value.Word = cache.ReadUInt16(addrsArr[i]).Value;
                    break;

                case DataType.SHORT:
                    items[i].Value.Int16 = cache.ReadInt16(addrsArr[i]).Value;
                    break;

                case DataType.DWORD:
                    items[i].Value.DWord = cache.ReadUInt32(addrsArr[i]).Value;
                    break;

                case DataType.INT:
                    items[i].Value.Int32 = cache.ReadInt32(addrsArr[i]).Value;
                    break;

                case DataType.FLOAT:
                    items[i].Value.Single = cache.ReadFloat(addrsArr[i]).Value;
                    break;

                case DataType.STR:
                    var item = cache.ReadString(addrsArr[i], addrsArr[i].DataSize);
                    break;
                }
                items[i].Quality   = QUALITIES.QUALITY_GOOD;
                items[i].TimeStamp = now;
            }
            return(items);
        }
Beispiel #2
0
        public static int PLCWriteMultiple(this IPLCDriver plc, ICache cache, DeviceAddress[] addrArr, object[] buffer,
                                           int limit)
        {
            if (cache == null || addrArr == null || buffer == null || addrArr.Length != buffer.Length)
            {
                return(-1);
            }
            if (addrArr.Length == 1)
            {
                return(plc.WriteValue(addrArr[0], buffer[0]));
            }
            lock (plc) //不锁定会有并发冲突问题;锁定也不能保障绝对安全,如有人现场操作会导致数据刷新
            {
                List <PDUArea> areas  = cache.AssignFromPDU(plc.PDU, addrArr);
                int            offset = 0;
                foreach (PDUArea area in areas)
                {
                    byte[] rcvBytes = plc.ReadBytes(area.Start, (ushort)area.Len);
                    if (rcvBytes == null)
                    {
                        return(-1);
                    }
                    Buffer.BlockCopy(rcvBytes, 0, cache.Cache, offset, rcvBytes.Length);
                    offset += rcvBytes.Length / cache.ByteCount;
                }

                DeviceAddress start      = addrArr[0];
                int           startIndex = 0;
                int           endIndex   = 0;
                while (endIndex < addrArr.Length)
                {
                    if (start.Area != addrArr[endIndex].Area || start.DBNumber != addrArr[endIndex].DBNumber ||
                        endIndex - startIndex >= limit)
                    {
                        for (int i = startIndex; i < endIndex; i++)
                        {
                            cache.WriteValue(addrArr[i], buffer[i]);
                        }

                        int    c1    = start.CacheIndex;
                        int    c2    = addrArr[endIndex - 1].CacheIndex;
                        byte[] bytes = new byte[cache.ByteCount * (c2 - c1 + 1)];
                        Buffer.BlockCopy(cache.Cache, c1, bytes, 0, bytes.Length);
                        if (plc.WriteBytes(start, bytes) < 0)
                        {
                            return(-1);
                        }
                        start      = addrArr[endIndex];
                        startIndex = endIndex;
                    }

                    endIndex++;
                }
            }

            return(0);
        }
Beispiel #3
0
        protected virtual int Poll()
        {
            if (_plcReader.IsClosed)
            {
                return(-1);
            }
            byte[] cache  = (byte[])_cacheReader.Cache;
            int    offset = 0;

            foreach (PDUArea area in _rangeList)
            {
                byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据
                if (rcvBytes == null)
                {
                    //_plcReader.Connect();
                    return(-1);
                }
                else
                {
                    int index = area.StartIndex;//index指向_items中的Tag元数据
                    int count = index + area.Count;
                    while (index < count)
                    {
                        DeviceAddress addr   = _items[index].Address;
                        int           iByte  = addr.CacheIndex;
                        int           iByte1 = iByte - offset;
                        if (addr.VarType == DataType.BOOL)
                        {
                            int           tmp  = rcvBytes[iByte1] ^ cache[iByte];
                            DeviceAddress next = addr;
                            if (tmp != 0)
                            {
                                while (addr.Start == next.Start)
                                {
                                    if ((tmp & (1 << next.Bit)) > 0)
                                    {
                                        _changedList.Add(index);
                                    }
                                    if (++index < count)
                                    {
                                        next = _items[index].Address;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                while (addr.Start == next.Start && ++index < count)
                                {
                                    next = _items[index].Address;
                                }
                            }
                        }
                        else
                        {
                            ushort size = addr.DataSize;
                            for (int i = 0; i < size; i++)
                            {
                                if (rcvBytes[iByte1 + i] != cache[iByte + i])
                                {
                                    _changedList.Add(index);
                                    break;
                                }
                            }
                            index++;
                        }
                    }
                    for (int j = 0; j < rcvBytes.Length; j++)
                    {
                        cache[j + offset] = rcvBytes[j];//将PLC读取的数据写入到CacheReader中
                    }
                }
                offset += rcvBytes.Length;
            }
            return(1);
        }
Beispiel #4
0
        /// <summary>
        /// 主通信流程:Step 2:从通信模块中获取数据,并记录变化量地址
        /// </summary>
        protected virtual void Poll()
        {
            if (_plcReader.IsClosed)
            {
                return;
            }
            byte[] cache  = (byte[])_cacheReader.Cache; //这个是缓存里面的数据,用来和新取得数据进行对比
            int    offset = 0;                          //收到的新的字节中的偏移量

            foreach (PDUArea area in _rangeList)
            {
                byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//逐一从PLC读取数据读取指定的长度(对于我们程序就是UDP从网络端口读取的数据),对于我们的程序就是固定一个长度就好

                if (rcvBytes == null)
                {
                    //_plcReader.Connect();
                    continue;
                }
                else
                {
                    int index = area.StartIndex;    //index指向_items中的Tag元数据  index 是Itag的索引
                    int count = index + area.Count; //count 是总共的Itag 列表的个数,Count 指单次读取的字节中所包含的 Itag个数
                    while (index < count)
                    {
                        DeviceAddress addr   = _items[index].Address; //根据在Itag里面的索引,得到内存中的地址
                        int           iByte  = addr.CacheIndex;       //在内存中的字节索引地址
                        int           iByte1 = iByte - offset;        //在内存中,因为前一个PDUArea块的存在,偏移量,所以到读取的新的字节数组中,要求减去这个偏移量
                        if (addr.VarType == DataType.BOOL)
                        {
                            int           tmp  = rcvBytes[iByte1] ^ cache[iByte]; //对比一下内存里面的值,看有没有发生变化,有的话就需要更新,保留异或位
                            DeviceAddress next = addr;
                            if (tmp != 0)                                         //看整个字节里面的8个位有没有发生变化
                            {
                                while (addr.Start == next.Start)                  //下面while循环比较同一个字节里面不同的位,是否都发生了变化,因为起始地址都是按字节计算的
                                {
                                    if ((tmp & (1 << next.Bit)) > 0)
                                    {
                                        _changedList.Add(index);                             //tmp里面记录了所有发生变化的位,后面的Itag要是起始地址相同,说明是一个字节里面不同的位有变化
                                    }
                                    if (++index < count)
                                    {
                                        next = _items[index].Address;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                while (addr.Start == next.Start && ++index < count)
                                {
                                    next = _items[index].Address;
                                }
                            }
                        }
                        else
                        {
                            ushort size = addr.DataSize;//把单个Itag字节长度取出来,一个一个字节进行对比
                            for (int i = 0; i < size; i++)
                            {
                                if (iByte1 + i < rcvBytes.Length && rcvBytes[iByte1 + i] != cache[iByte + i])//只要发现长度size当中有任何变化的值,就是值有变化
                                {
                                    _changedList.Add(index);
                                    break;
                                }
                            }
                            index++;
                        }
                    }
                    for (int j = 0; j < rcvBytes.Length; j++)
                    {
                        cache[j + offset] = rcvBytes[j];//将PLC读取的数据写入到CacheReader中,所有都更新到内存中,但只推送那些变化的值
                    }
                }
                offset += rcvBytes.Length;
            }
        }
Beispiel #5
0
        protected virtual unsafe void Poll()
        {
            short[] cache = (short[])_cacheReader.Cache;
            int     k     = 0;

            foreach (PDUArea area in _rangeList)
            {
                byte[] rcvBytes = _plcReader.ReadBytes(area.Start, (ushort)area.Len);//从PLC读取数据
                if (rcvBytes == null)
                {
                    k += (area.Len + 1) / 2;
                    continue;
                }
                else
                {
                    int len = rcvBytes.Length / 2;
                    fixed(byte *p1 = rcvBytes)
                    {
                        short *prcv  = (short *)p1;
                        int    index = area.StartIndex;//index指向_items中的Tag元数据
                        int    count = index + area.Count;

                        while (index < count)
                        {
                            DeviceAddress addr    = _items[index].Address;
                            int           iShort  = addr.CacheIndex;
                            int           iShort1 = iShort - k;
                            if (addr.VarType == DataType.BOOL)
                            {
                                int           tmp  = prcv[iShort1] ^ cache[iShort];
                                DeviceAddress next = addr;
                                if (tmp != 0)
                                {
                                    while (addr.Start == next.Start)
                                    {
                                        if ((tmp & (1 << next.Bit)) > 0)
                                        {
                                            _changedList.Add(index);
                                        }
                                        if (++index < count)
                                        {
                                            next = _items[index].Address;
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    while (addr.Start == next.Start && ++index < count)
                                    {
                                        next = _items[index].Address;
                                    }
                                }
                            }
                            else
                            {
                                if (addr.ByteOrder.HasFlag(ByteOrder.BigEndian))
                                {
                                    for (int i = 0; i < addr.DataSize / 2; i++)
                                    {
                                        prcv[iShort1 + i] = IPAddress.HostToNetworkOrder(prcv[iShort1 + i]);
                                    }
                                }
                                if (addr.DataSize <= 2)
                                {
                                    if (prcv[iShort1] != cache[iShort])
                                    {
                                        _changedList.Add(index);
                                    }
                                }
                                else
                                {
                                    int size = addr.DataSize / 2;
                                    for (int i = 0; i < size; i++)
                                    {
                                        if (prcv[iShort1 + i] != cache[iShort + i])
                                        {
                                            _changedList.Add(index);
                                            break;
                                        }
                                    }
                                }
                                index++;
                            }
                        }
                        short[] prcvShorts = new short[len];
                        for (int i = 0; i < len; i++)
                        {
                            prcvShorts[i] = prcv[i];
                        }

                        //改成Array.Copy 由于线程安全的问题
                        Array.Copy(prcvShorts, 0, cache, k, len);

                        /*
                         * for (int j = 0; j < len; j++)
                         * {
                         *  cache[j + offset] = prcv[j];
                         * }//将PLC读取的数据写入到CacheReader中
                         */
                    }

                    k += len;
                }
            }
        }