public ModbusAdapterContext(DeviceBase canDevice, File modbusDevice) { CanDevice = new CAN(); CanDevice.NetworkId = canDevice.Network.NetworkId; CanDevice.NodeId = canDevice.NodeId; ModbusDevice = new Modbus(); ModbusDevice.FileNumber = modbusDevice.Number; }
/// <summary> /// Создаёт контроллер сети Modbus из файла конфигурации сети /// </summary> /// <param name="pathToXmlFile">Путь + название файла конфигурации сети *.xml</param> /// <param name="pathToXsdFile">Путь + название файла файла схемы для файла конфигурации *.xsd</param> /// <returns>Если возникла ошибка возвращается null, если процесс создания /// успешно завершён возвращается контроллер сети</returns> public static NetworkController Create(String pathToXmlFile, String pathToXsdFile) { XmlReaderSettings xmlrdsettings; XmlReader reader; NetworkController network; Device device; Coil coil; DiscreteInput dinput; HoldingRegister hregister; InputRegister iregister; File file; Record record; List<Device> devices; String networkName; networkName = String.Empty; devices = new List<Device>(); xmlrdsettings = new XmlReaderSettings(); xmlrdsettings.IgnoreComments = true; xmlrdsettings.IgnoreWhitespace = true; xmlrdsettings.Schemas.Add("", pathToXsdFile); xmlrdsettings.ValidationType = ValidationType.Schema; //xmlrdsettings.ValidationEventHandler += // new ValidationEventHandler(EventHandler_vr_ValidationEventHandler); reader = XmlReader.Create(pathToXmlFile, xmlrdsettings); try { while(reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { if (!reader.IsEmptyElement) { switch (reader.Name) { case "Network": { if (reader.HasAttributes) { // Получаем наименование сети networkName = reader.GetAttribute("Name"); //network.NetworkName = reader.GetAttribute("Name"); } else { throw new Exception(String.Format( "Ошибка в строке {0}.Элемент Network не имеет свойства Name", reader.Settings.LineNumberOffset.ToString())); } break; } case "Device": { if (reader.HasAttributes) { device = new Device(Byte.Parse(reader.GetAttribute("Address"))); device.Description = reader.GetAttribute("Description"); device.Status = (Status)Enum.Parse(typeof(Status), reader.GetAttribute("Status")); //network.Devices.Add(device); devices.Add(device); } else { throw new Exception(String.Format( "Ошибка в строке {0}.Элемент Device не имеет свойств", reader.Settings.LineNumberOffset.ToString())); } break; } case "Coil": { if (reader.HasAttributes) { Boolean value; UInt16 address = UInt16.Parse(reader.GetAttribute("Address")); reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Value") { reader.Read(); value = Boolean.Parse(reader.Value); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент Coil не содержит элемент Value", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент Coil содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } reader.Read(); // EndElement Value reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Description") { reader.Read(); coil = new Coil(address, value, reader.Value); //network.Devices[network.Devices.Count - 1].Coils.Add(coil); devices[devices.Count - 1].Coils.Add(coil); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент Coil не содержит элемент Description", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент Coil содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}.Элемент Coil не имеет свойств", reader.Settings.LineNumberOffset.ToString())); } break; } case "DiscreteInput": { if (reader.HasAttributes) { Boolean value; UInt16 address = UInt16.Parse(reader.GetAttribute("Address")); reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Value") { reader.Read(); value = Boolean.Parse(reader.Value); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент DiscreteInput не содержит элемент Value", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент DiscreteInput содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } reader.Read(); // EndElement Value reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Description") { reader.Read(); dinput = new DiscreteInput(address, value, reader.Value); //network.Devices[network.Devices.Count - 1].DiscretesInputs.Add(dinput); devices[devices.Count - 1].DiscretesInputs.Add(dinput); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент DiscreteInput не содержит элемент Description", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент DiscreteInput содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}.Элемент DiscreteInput не имеет свойств", reader.Settings.LineNumberOffset.ToString())); } break; } case "HoldingRegister": { if (reader.HasAttributes) { UInt16 value; UInt16 address = UInt16.Parse(reader.GetAttribute("Address")); reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Value") { reader.Read(); value = UInt16.Parse(reader.Value); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент HoldingRegister не содержит элемент Value", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент HoldingRegister содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } reader.Read(); // EndElement Value reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Description") { reader.Read(); hregister = new HoldingRegister(address, value, reader.Value); //network.Devices[network.Devices.Count - 1].HoldingRegisters.Add(hregister); devices[devices.Count - 1].HoldingRegisters.Add(hregister); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент HoldingRegister не содержит элемент Description", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент HoldingRegister содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}.Элемент HoldingRegister не имеет свойств", reader.Settings.LineNumberOffset.ToString())); } break; } case "InputRegister": { if (reader.HasAttributes) { UInt16 value; UInt16 address = UInt16.Parse(reader.GetAttribute("Address")); reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Value") { reader.Read(); value = UInt16.Parse(reader.Value); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент InputRegister не содержит элемент Value", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент InputRegister содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } reader.Read(); // EndElement Value reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Description") { reader.Read(); iregister = new InputRegister(address, value, reader.Value); //network.Devices[network.Devices.Count - 1].InputRegisters.Add(iregister); devices[devices.Count - 1].InputRegisters.Add(iregister); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент InputRegister не содержит элемент Description", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент InputRegister содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}.Элемент InputRegister не имеет свойств", reader.Settings.LineNumberOffset.ToString())); } break; } case "File": { file = new File(UInt16.Parse(reader.GetAttribute("Number")), reader.GetAttribute("Description")); //network.Devices[network.Devices.Count - 1].Files.Add(file); devices[devices.Count - 1].Files.Add(file); break; } case "Record": { UInt16 number = UInt16.Parse(reader.GetAttribute("Number")); String description = reader.GetAttribute("Description"); // Вычитываем следующий элемент. Это долно быть Value reader.Read(); if (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Value") { reader.Read(); record = new Record(number, UInt16.Parse(reader.Value), description); //device = network.Devices[network.Devices.Count - 1]; //device.Files[device.Files.Count - 1].Records.Add(record); device = devices[devices.Count - 1]; device.Files[device.Files.Count - 1].Records.Add(record); } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент Record не содержит элемент Value", reader.Settings.LineNumberOffset.ToString())); } } else { throw new Exception(String.Format( "Ошибка в строке {0}. Элемент Record содержит элемент недопустимого типа", reader.Settings.LineNumberOffset.ToString())); } break; } } } } // End of if (reader.NodeType == XmlNodeType.Element) } // End of while(reader.Read()) } //catch (XmlException ex) //{ // if (reader != null) // { // reader.Close(); // } // throw; //} catch //(Exception ex) { if (reader != null) { reader.Close(); } throw; } finally { if (reader != null) { reader.Close(); } } // Создаём сеть из полученных данных network = new NetworkController(networkName, null); foreach (Device item in devices) { network.Devices.Add(item); } return network; }
//--------------------------------------------------------------------------- private void AddFile() { UInt16 number; Device device; File file; device = (Device)_BindingSourceDevicesList.Current; for (number = 1; number < 10000; number++) { if (!device.Files.Contains(number)) { file = new File(number, String.Empty); //_BindingSourceFiles.Add(file); //_BindingSourceFiles.EndEdit(); device.Files.Add(file); _BindingSourceDevicesList.ResetCurrentItem(); if (device.Files.Count > 0) { _ToolStripMenuItemRemoveFile.Enabled = true; _ContextMenuStripRecords.Enabled = true; } if (device.Files.Count > 9999) { _ToolStripMenuItemAddFile.Enabled = false; } return; } } throw new InvalidOperationException( "Неудалось добавить новый файл в устройство, все номера заняты"); }
public static void Copy(File modbusDevice, DeviceBase canDevice) { Record rec; UInt16 index; UInt32 var32; if (canDevice.DeviceType != DeviceType.KIP_BATTERY_POWER_v1) { throw new InvalidCastException("Требуется устройство CAN типа КИП-9811"); } if (modbusDevice.Records[KIP9811Address.VisitingCard.DeviceType].Value != (UInt16)DeviceType.KIP_BATTERY_POWER_v1) { throw new InvalidCastException("Требуется устройство modbus типа КИП-9811"); } // Адреса, которые обрабатываются по особому UInt16[] exclusions = new ushort[] { 0x000A, 0x000B, 0x000C, 0x000E, 0x0014, 0x0019, 0x0020, 0x0024, 0x0025, 0x0026, 0x0036, 0x0037 }; // Адреса, которые исключаются из обработки UInt16[] nothandled = new ushort[] { 0x0000, 0x0006, 0x0007, 0x0008, 0x0009, 0x000D, 0x000E }; // Копируем данные foreach (UInt16 modbusAddress in _TableAddress.Keys) { // Исключаем из обработки адреса if (Exist(nothandled, modbusAddress)) { continue; } // Адреса для обработки особым способом, // так же пропускаем, их обработаем ниже if (Exist(exclusions, modbusAddress)) { continue; } // Получаем индекс объекта CAN-устройства index = _TableAddress[modbusAddress]; // Копируем значение объекта в запись modbus modbusDevice.Records[modbusAddress].Value = (UInt16)canDevice.ObjectDictionary[index].Value; } // Теперь обрабатываем сложные параметры // 0x0007 //modbusDevice.Records[0x0007].Value = 0; //TODO Код производителя, всега неопределён // 0x000A modbusDevice.Records[0x000A].Value = Convert.ToUInt16(canDevice.NodeId); // 0x000B if (canDevice.Status == DeviceStatus.CommunicationError) { modbusDevice.Records[0x000B].Value = 0; } else { modbusDevice.Records[0x000B].Value = 1; } // 0x000C //modbusDevice.Records[0x000C].Value = 0; //TODO // 0x000E switch (canDevice.Status) { case DeviceStatus.CommunicationError: case DeviceStatus.ConfigurationError: case DeviceStatus.Stopped: { modbusDevice.Records[0x000E].Value = (UInt16)DeviceStatus.Stopped; // Stopped break; } case DeviceStatus.Operational: { modbusDevice.Records[0x000E].Value = (UInt16)DeviceStatus.Operational; break; } case DeviceStatus.Preoperational: { modbusDevice.Records[0x000E].Value = (UInt16)DeviceStatus.Preoperational; break; } default: { throw new NotSupportedException(); } } //0x0014 TODO //0x0019 TODO //0x0020 TODO //0x0024 modbusDevice.Records[0x0024].Value = canDevice.ElectrodeArea; //0x0025, 0x0026 var32 = (UInt32)canDevice.GetObject(_TableAddress[0x0025]); modbusDevice.Records[0x0025].Value = (UInt16)(var32 >> 16); var32 = (UInt32)canDevice.GetObject(_TableAddress[0x0026]); modbusDevice.Records[0x0026].Value = (UInt16)var32; //0x0036, 0x0037 var32 = Unix.ToUnixTime((DateTime)canDevice.GetObject(_TableAddress[0x0036])); modbusDevice.Records[0x0036].Value = (UInt16)(var32 >> 16); var32 = Unix.ToUnixTime((DateTime)canDevice.GetObject(_TableAddress[0x0037])); unchecked { modbusDevice.Records[0x0037].Value = (UInt16)var32; } return; }
/// <summary> /// Обновляет данные modbus-файла на основе переданного CAN-устройства /// </summary> /// <param name="modbusDevice"></param> /// <param name="canDevice"></param> private static void UdateDevice( File modbusDevice, NGK.CAN.ApplicationLayer.Network.Devices.DeviceBase canDevice) { NGK.CAN.ApplicationLayer.Network.Devices.DeviceType type = (NGK.CAN.ApplicationLayer.Network.Devices.DeviceType)modbusDevice.Records[ModbusAddresses .ModbusVisitingCard.VisitingCard.DeviceType].Value; switch (type) { case NGK.CAN.ApplicationLayer.Network.Devices.DeviceType.KIP_BATTERY_POWER_v1: { RemappingTableKip9811.Copy(modbusDevice, canDevice); break; } default: { throw new NotSupportedException(); } } }
/// <summary> /// Создаёт modbus-файл устройства КИП БИ(У)-01 /// </summary> /// <returns>Modbus файл</returns> private File CreateKIP01() { File file = new File(); // Создаём визитную карту устройства file.Records.Add(new Record(0x0000, 0x2653, "Тип устройства")); file.Records.Add(new Record(0x0001, 0, "Версия ПО")); file.Records.Add(new Record(0x0002, 0, "Версия Аппаратуры")); file.Records.Add(new Record(0x0003, 0, "Серийный номер: High")); file.Records.Add(new Record(0x0004, 0, "Серийный номер: Middle")); file.Records.Add(new Record(0x0005, 0, "Серийный номер: Low")); file.Records.Add(new Record(0x0006, 0, "CRC16")); file.Records.Add(new Record(0x0007, 0, "Код производителя")); // Добавляем служебную информацию //(2 - Устройство Сети CAN) file.Records.Add(new Record(0x0008, 2, "Тип сети")); // Не реализованно - всегда 0 file.Records.Add(new Record(0x0009, 0, "Номер сети")); file.Records.Add(new Record(0x000A, 1, "Сетевой адрес")); file.Records.Add(new Record(0x000B, 1, "Наличие связи с устройством")); // Добавляем данные специфичные для объектов словаря CAN устройства file.Records.Add(new Record(0x000C, 0, "Регистр ошибок")); file.Records.Add(new Record(0x000D, 0, "Регистр ошибок регистрации")); file.Records.Add(new Record(0x000E, 0, "Состояние устройства")); file.Records.Add(new Record(0x000F, 0, "Защитный потенциал")); file.Records.Add(new Record(0x0010, 0, "Поляризационный потенциал подземного трубопровода")); file.Records.Add(new Record(0x0011, 0, "Ток катодной защиты в точ-ке дренажа методом измере-ния напряжения на внешнем шунте")); file.Records.Add(new Record(0x0012, 0, "Наведённое переменное напряжение на трубопровод")); file.Records.Add(new Record(0x0013, 0, "Ток поляризации вспомогательного электрода")); file.Records.Add(new Record(0x0014, 0, "Плотность тока поляризации вспомогательного электрода")); file.Records.Add(new Record(0x0015, 0, "Ток измерительного канала 1")); file.Records.Add(new Record(0x0016, 0, "Ток измерительного канала 2")); file.Records.Add(new Record(0x0017, 0, "Глубина коррозии датчика ИКП с устройства УСИКПСТ")); file.Records.Add(new Record(0x0018, 0, "Скорость коррозии датчика ИКП с устройства УСИКПСТ")); file.Records.Add(new Record(0x0019, 0, "Состояние УСИКПСТ")); file.Records.Add(new Record(0x001A, 0, "Состояние пластины датчика «1» скорости коррозии 30,0-100,0 Ом")); file.Records.Add(new Record(0x001B, 0, "Состояние пластины датчика «2» скорости коррозии 30,0-100,0 Ом")); file.Records.Add(new Record(0x001C, 0, "Состояние пластины датчика «3» скорости коррозии 30,0-100,0 Ом")); file.Records.Add(new Record(0x001D, 0, "Ток натекания ВЭ постоянный")); file.Records.Add(new Record(0x001E, 0, "Ток натекания ВЭ переменный")); file.Records.Add(new Record(0x001F, 0, "Плотность тока натекания ВЭ постоянного")); file.Records.Add(new Record(0x0020, 0, "Плотность тока натекания ВЭ переменного")); file.Records.Add(new Record(0x0021, 0xFFFF, "Зарезервировано")); file.Records.Add(new Record(0x0022, 0, "Напряжение встроенного элемента питания")); file.Records.Add(new Record(0x0023, 0, "Температура встроенного датчика БИ(У)")); file.Records.Add(new Record(0x0024, 0, "Площадь вспомогательного электрода (ВЭ)")); file.Records.Add(new Record(0x0025, 0, "Период измерений и передачи информации: High")); file.Records.Add(new Record(0x0026, 0, "Период измерений и передачи информации: Low")); file.Records.Add(new Record(0x0027, 0xFFFF, "Зарезервировано")); file.Records.Add(new Record(0x0028, 0, "Период опроса УСИКПСТ")); file.Records.Add(new Record(0x0029, 0, "Период опроса датчиков коррозии")); file.Records.Add(new Record(0x002A, 0, "Период опроса измерительного канала 1 4-20 мА")); file.Records.Add(new Record(0x002B, 0, "Период опроса измерительного канала 2 4-20 мА")); file.Records.Add(new Record(0x002C, 0, "Номинальный ток внешнего шунта (А)")); file.Records.Add(new Record(0x002D, 0, "Флаг разрешения работы канала измерения поляризационного потенциала подземного трубопровода.")); file.Records.Add(new Record(0x002E, 0, "Флаг разрешения работы канала измерения защитного потенциала.")); file.Records.Add(new Record(0x002F, 0, "Флаг разрешения работы канала измерения тока катодной защиты в точке дренажа методом измерения напряжения на внешнем шунте.")); file.Records.Add(new Record(0x0030, 0, "Флаг разрешения работы канала тока поляризации вспомогательного электрода")); file.Records.Add(new Record(0x0031, 0, "Флаг разрешения работы канала измерения наведённого переменного напряжения на трубопровод")); file.Records.Add(new Record(0x0032, 0, "Флаг разрешения передачи слова состояния")); file.Records.Add(new Record(0x0033, 0, "Флаг разрешения работы канала измерения тока натекания ВЭ постоянного")); file.Records.Add(new Record(0x0034, 0, "Флаг разрешения работы канала измерения тока натекания ВЭ переменного")); file.Records.Add(new Record(0x0035, 0, "Разрешение или запрещение передачи PDO")); file.Records.Add(new Record(0x0036, 0, "Текущее время устройства: High")); file.Records.Add(new Record(0x0037, 0, "Текущее время устройства: Low")); return file; }