Профиль должен быть заполнен на русском языке кириллицей. Заполнение профиля заведомо ложными или некорректными данными - причина возможного отказа в регистрации на форуме.

Подключение к modbus из службы

RS-485, ProfiBUS, 4-20 mA, Wi-Fi, GSM и так далее

Автор темы
andrej35
новенький
новенький
Сообщения: 2
Зарегистрирован: 15 фев 2016, 10:37
Ф.И.О.: Андрей
Благодарил (а): 2 раза

Подключение к modbus из службы

Сообщение andrej35 » 15 фев 2016, 10:43

Добрый день.
Имеется компьютер с modbus slave, нужно написать службу (сервис) modbus master, которая будет запущена на другом пк и будет писать данные в базу. Использую класс ModbusTCP. Проблема заключается в том что при добавление соединения к modbus перестает отрабатывать таймер timer1_Elapsed. В данный момент в файл service и в бд, пишется дата и время. + Должен записываться данные из регистра в файл. Пробовал использовать try и catch но записывается только (Сервис стартовал и Сервис остановлен). Программа эмуляции слейва modbus slave. Подскажите в чем проблема. Спасибо.
[+] код C#
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Data.OracleClient;
using System.Text;
using System.Threading;
using ModbusTCP;

namespace WindowsService3
{

public partial class Service1 : ServiceBase
{
private ModbusTCP.Master MBmaster;
private byte[] data;
string res=" ";
private StreamWriter file;
private System.Timers.Timer timer1;

OracleConnection connnection = new OracleConnection("Соединение с бд");

public Service1()
{
InitializeComponent();
}

protected override void OnStart(string[] args)
{
file = new StreamWriter(new FileStream(@"c:\Service.txt", System.IO.FileMode.Append));
this.file.WriteLine("Сервис стартовал" +" "+ DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"));
this.file.Flush();
this.timer1 = new System.Timers.Timer();
this.timer1.Enabled = true;
this.timer1.Interval = 10000;
this.timer1.Elapsed +=new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);
this.timer1.AutoReset = true;
this.timer1.Start();
}

private bool SaveDateTime(DateTime dt)
{
OracleCommand ocmn = new OracleCommand();
OracleDataAdapter oda = new OracleDataAdapter();
DataSet ds = new DataSet();
ocmn.CommandText = "test.mod1";
ocmn.CommandType = CommandType.StoredProcedure;
ocmn.Connection = connnection;
oda.SelectCommand = ocmn;
ocmn.Parameters.Add("dt", OracleType.DateTime);
ocmn.Parameters["dt"].Value = dt;
if (connnection.State != ConnectionState.Open)
connnection.Open();
try
{
ocmn.ExecuteNonQuery();
return true;
}
catch (Exception e)
{
return false;
}
finally
{
connnection.Close();
}
}

private void ShowAs(object sender, System.EventArgs e)
{
double[] iword = new double[1];
string[] word = new string[1];
if (data.Length < 2) return;
iword = new double[data.Length / 2];
word = new string[data.Length / 2];
for (int x = 0; x < data.Length; x = x + 2)
{
iword[x / 2] = data[x] * 256 + data[x + 1];
word[x / 2] = iword[x / 2].ToString();
}
res = word[0].ToString();
}

private void MBmaster_OnResponseData(ushort ID, byte unit, byte function, byte[] values)
{
data = values;
ShowAs(null, null);
}

private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
MBmaster = new Master("127.0.0.1", 502);
MBmaster.OnResponseData += new ModbusTCP.Master.ResponseData(MBmaster_OnResponseData);
MBmaster.ReadHoldingRegister(3, 1, 0, 1);

bool check = SaveDateTime(DateTime.Now);

if (check == true)
{

this.file.WriteLine(res,DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + " OK!!! ");
}
else
{
this.file.WriteLine(res,DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + " NET!!! ");
}
this.file.Flush();
}

protected override void OnStop()
{
this.timer1.Stop();
this.file.WriteLine("Сервис остановлен" + " " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss"));
this.file.Flush();
this.file.Close();

}
}
}

Аватара пользователя

TEB
специалист по DEIF
специалист по DEIF
Сообщения: 7878
Зарегистрирован: 17 июн 2008, 15:01
Ф.И.О.: Евгений свет Брониславович
Благодарил (а): 35 раз
Поблагодарили: 63 раза
Контактная информация:

Подключение к modbus из службы

Сообщение TEB » 15 фев 2016, 11:23

Зайду глобально.

Можно же просто взять для этого СКАДА и настроить только опрос и запись в БД.
А разработка займёт время, то есть денег тоже стоит, и потом никакой техподдержки.
По вопросам работы Форума можно обратиться ко мне, или по этим контактам.

Аватара пользователя

VADR
администратор
администратор
Сообщения: 2405
Зарегистрирован: 25 июл 2008, 06:12
Ф.И.О.: Диев Александр Васильевич
Благодарил (а): 19 раз
Поблагодарили: 25 раз

Подключение к modbus из службы

Сообщение VADR » 15 фев 2016, 12:39

В ту же корзину: можно взять готовый OPC-сервер для modbus (каковых существует более одной штуки) и готовую систему хранения данных, умеющую забирать данные по OPC (таких тоже более одной). На первый взгляд это может показаться дороже, чем собственная разработка, но в дальнейшем, когда источников данных станет больше, а список требований - длиннее...
Повторное использование кода не отменяет повторного использования мозга при его повторном использовании.


Автор темы
andrej35
новенький
новенький
Сообщения: 2
Зарегистрирован: 15 фев 2016, 10:37
Ф.И.О.: Андрей
Благодарил (а): 2 раза

Подключение к modbus из службы

Сообщение andrej35 » 15 фев 2016, 13:00

Спасибо за ответы.
Если бы была возможность, то конечно же поставил OPC- сервер, но в данном случае такой возможности нету.
Нужно просто данные из регистров в базу писать по таймеру. Буду дальше разбираться.

Аватара пользователя

MuadDib
не первый раз у нас
не первый раз у нас
Сообщения: 359
Зарегистрирован: 31 июл 2010, 08:12
Ф.И.О.: Журавлев Павел Евгеньевич
Поблагодарили: 1 раз

Подключение к modbus из службы

Сообщение MuadDib » 16 фев 2016, 06:36

А откуда вы знаете, что у вас перестал отрабатывать таймер? Чтобы в этом убедиться, нужно написать что-нибудь в файл в самом начале метода обработчика.

Далее. Поле res вы используете неправильно. Обработчик OnResponseData должен что-то с ним делать, но код file.WriteLine() обращается к содержимому поля сразу же, не дожидаясь реакции обработчика. Ну и создание нового объекта Master на каждом событии таймера без последующей очистки - явный косяк.

Ну и раз задаете вопрос о классе из сторонней библиотеки, надо хотя бы ссылку давать на источник этого компонента.

И еще один момент. Не стоит юзать Timer таким образом. Лучше создайте в методе OnStart() поток и работайте в нем. Вам же проще будет.


SaNNy
осмотрелся
осмотрелся
Сообщения: 129
Зарегистрирован: 01 фев 2010, 10:37
Ф.И.О.: Ананьев А.А.
Благодарил (а): 1 раз
Поблагодарили: 1 раз

Подключение к modbus из службы

Сообщение SaNNy » 17 фев 2016, 22:40

Вообще, конечно, такой код я бы в промышленном решении побоялся бы использовать. Это может обернуться многими проблемами.

Некоторые комментарии по коду:
1. Создание объекта Modbus Master на каждом интервале таймера оборачивается ненужной фрагментацией памяти и в конце концов перестает работать.
2. Обработка ошибок практически отсутствует. Для логирования лучше использовать готовые инструменты, например NLog, System.Diagnostic.Trace и др.
3. Создание подключения к базе данных на каждом интервале таймера, зачем так неэкономно тратить ресурсы компьютера?
4. Запись в бд и в файл в обработчике timer1_Elapsed плохо. Лучше в нем запускать отдельный поток и в нем выполнять эти действия.
5. Для конкатенции строк лучше использовать StringBuilder
6. Переменным лучше давать осмысленные имена и придерживаться General Naming Conventions (https://msdn.microsoft.com/en-us/librar ... 10%29.aspx)
7. Параметры сервиса, такие как ip адрес, порт и пр. лучше выносить в отдельный кофигурационный файл.


Вернуться в «Интерфейсы, протоколы, связь»



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 0 гостей