public interface IS7ConnService
{
void ConnPlc(string myIp, int dbNum, int startByte);
bool MyIsConnected
{
get;
}
Plc S7Plc { get; }
}
public class DB33Ioc : INotifyPropertyChanged
{
private bool b1;
private bool b2;
public bool B1
{
get => b1;
set
{
if (b1 != value && value == true)
{
NotifyPropertyChanged(nameof(B1));
}
b1 = value;
}
}
public bool B2
{
get => b2;
set
{
if (b2 != value && value == true)
{
NotifyPropertyChanged(nameof(B2));
}
b2 = value;
}
}
public bool B3 { get; set; }
public short S1 { get; set; }
public short S2 { get; set; }
public short S3 { get; set; }
public float R1 { get; set; }
public float R2 { get; set; }
public float R3 { get; set; }
[S7String(S7StringType.S7String, 30)]
public string Str { get; set; } = string.Empty;
public virtual void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler? PropertyChanged;
}
通信库:
public class S7NioService<T> : IS7ConnService
where T : class, new()
{
private int errorTimes = 0;
//private PeriodicTimer timer = new(TimeSpan.FromMilliseconds(100));
private CancellationTokenSource cts = new();
public bool MyIsConnected { get; set; }
public Plc? S7Plc { get; set; }
private Channel<T> messageChannel;
private readonly ILogger<S7NioService<T>> logger;
private T nioData;
public S7NioService(ILogger<S7NioService<T>> logger, T nioData)
{
this.logger = logger;
this.nioData = nioData;
var opt = new BoundedChannelOptions(2000)
{
FullMode = BoundedChannelFullMode.DropOldest,
Capacity = 2000
};
messageChannel = Channel.CreateBounded<T>(opt);
Task.Run(async () =>
{
await foreach (T item in messageChannel.Reader.ReadAllAsync())
{
CopyProperties(item, this.nioData);
//this.nioData = item;
}
});
}
/// <summary>
///
/// </summary>
/// <param name="myIp">Ip地址</param>
/// <param name="dbNum">Db号</param>
/// <param name="startByte">起始字节</param>
public void ConnPlc(string myIp, int dbNum, int startByte)
{
//using PeriodicTimer timer = new(TimeSpan.FromMilliseconds(100));
Task.Factory.StartNew(
async () =>
{
using PeriodicTimer timer = new(TimeSpan.FromMilliseconds(100));
while (!cts.IsCancellationRequested && await timer.WaitForNextTickAsync())
{
if (S7Plc == null || !MyIsConnected)
{
try
{
S7Plc = new Plc(CpuType.S71500, myIp, 0, 1);
S7Plc.Open();
S7Plc.ReadTimeout = 620;
S7Plc.WriteTimeout = 620;
MyIsConnected = S7Plc.IsConnected;
if (MyIsConnected)
{
logger.LogInformation("PlcSucessConn!");
}
}
catch (Exception ex)
{
if (errorTimes > 200)
{
errorTimes = 0;
logger.LogError("重试连接次数超过200");
}
errorTimes++;
S7Plc?.Close();
S7Plc = null;
MyIsConnected = false;
logger.LogError($"{ex.Message}:{DateTime.Now}");
logger.LogError("重连次数:" + errorTimes);
await Task.Delay(2000);
}
}
else if (MyIsConnected)
{
try
{
MyIsConnected = S7Plc.IsConnected;
errorTimes = 0;
var dbDataTemp = await S7Plc.ReadClassAsync<T>(dbNum, startByte);
//T nioDataTemp = new();
//CopyProperties(dbDataTemp, nioDataTemp);
if (dbDataTemp != null)
{
await messageChannel.Writer.WriteAsync(dbDataTemp);
}
//messageChannel.Writer.Complete(); //告诉reader 写完成信号
}
catch (Exception ex)
{
if (errorTimes > 200)
{
errorTimes = 0;
logger.LogError("读取时发生错误次数超过200");
}
errorTimes++;
await Task.Delay(2000);
logger.LogError($"读取时发生错误:{ex.Message}:{DateTime.Now}");
logger.LogError($"读取时发生错误次数:{errorTimes}");
S7Plc.Close();
MyIsConnected = false;
S7Plc = null;
}
}
}
},
cts.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Default
);
}
}
在初始化类调用:
public class StartupInitializationService : IHostedLifecycleService
{
private readonly IS7ConnService s7ConnService;
private DB33Ioc dB33Ioc;
private readonly ILogger<StartupInitializationService> logger;
private readonly SqliteSTRespository<Person> repPerson;
private readonly IHttpClientFactory clientFactory;
public StartupInitializationService(
IS7ConnService s7ConnService,
DB33Ioc dB33Ioc,
ILogger<StartupInitializationService> logger,
SqliteSTRespository<Person> repPerson,
IHttpClientFactory clientFactory
)
{
this.s7ConnService = s7ConnService;
this.dB33Ioc = dB33Ioc;
this.logger = logger;
this.repPerson = repPerson;
this.clientFactory = clientFactory;
}
/// <summary>
/// 第二早
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StartAsync(CancellationToken cancellationToken)
{
IConfigurationRoot? buider = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
string ip = buider["PlcIp"];
s7ConnService.ConnPlc(ip, 33, 0);
dB33Ioc.PropertyChanged += async (s, e) =>
{
if (e.PropertyName == "B2")
{
logger.LogWarning("B2被触发!");
logger.LogWarning(dB33Ioc.Str);
}
};
//List<Person> persons = new();
//for (int i = 0; i < 2; i++)
//{
// Person person = new()
// {
// Age = $"{i + 1}",
// Name = $"Tom{i + 1}"
// };
// persons.Add(person);
//}
//var a = repPerson.InsertRange(persons);
//logger.LogWarning(respositoryFt.GetById(1).PartNum);
return Task.CompletedTask;
}
/// <summary>
/// 停止后第二
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
/// <summary>
/// 启动完成
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
async Task IHostedLifecycleService.StartedAsync(CancellationToken cancellationToken)
{
using HttpClient? client = clientFactory.CreateClient();
client.Timeout = TimeSpan.FromSeconds(20);
//client.BaseAddress = new Uri(ip);
var baseRequest = new BaseRequest
{
Method = HttpMethod.Post,
Route = "/api/Test/MyClientTest",
Parameter = new Person { Age = "19", Name = "xiaoM" }
};
//MyHttpClient myHttpClient = new(ip, client);
MyHttpClient myHttpClient = new(client, "myIp");
var response = await myHttpClient.ExecuteAsync<Person>(baseRequest);
JsonSerializerOptions options = new()
{
WriteIndented = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
var str = JsonSerializer.Serialize(response, options);
logger.LogInformation($"started返回值: {str}");
//double ac = 0;
//int aaa = 0;
//short bbb = 0;
//Interlocked.Exchange(ref ac, 1.5);
//Interlocked.Exchange(ref aaa , bbb);
return;
}
/// <summary>
/// 最早
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task IHostedLifecycleService.StartingAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
/// <summary>
/// 已经停止
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task IHostedLifecycleService.StoppedAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
/// <summary>
/// 停止后第一
/// </summary>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task IHostedLifecycleService.StoppingAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
注入Ioc
builder.Services.AddSingleton<DB33Ioc>();
builder.Services.AddSingleton<IS7ConnService, S7NioService<DB33Ioc>>();
builder.Services.AddHostedService<StartupInitializationService>();