添加项目文件。
This commit is contained in:
parent
316344685d
commit
4d5444d8f6
|
|
@ -0,0 +1,25 @@
|
|||
**/.classpath
|
||||
**/.dockerignore
|
||||
**/.env
|
||||
**/.git
|
||||
**/.gitignore
|
||||
**/.project
|
||||
**/.settings
|
||||
**/.toolstarget
|
||||
**/.vs
|
||||
**/.vscode
|
||||
**/*.*proj.user
|
||||
**/*.dbmdl
|
||||
**/*.jfm
|
||||
**/azds.yaml
|
||||
**/bin
|
||||
**/charts
|
||||
**/docker-compose*
|
||||
**/Dockerfile*
|
||||
**/node_modules
|
||||
**/npm-debug.log
|
||||
**/obj
|
||||
**/secrets.dev.yaml
|
||||
**/values.dev.yaml
|
||||
LICENSE
|
||||
README.md
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.7.34221.43
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "langguanApi", "langguanApi\langguanApi.csproj", "{99745E10-D0AE-46BC-B23E-A24483532FEF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{99745E10-D0AE-46BC-B23E-A24483532FEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{99745E10-D0AE-46BC-B23E-A24483532FEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{99745E10-D0AE-46BC-B23E-A24483532FEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{99745E10-D0AE-46BC-B23E-A24483532FEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {9FA08BD4-39EF-4F6E-B3C9-990729D8ED1A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using langguanApi.Common.Redis;
|
||||
using langguanApi.Extensions.AutoDI;
|
||||
using Newtonsoft.Json;
|
||||
using StackExchange.Redis;
|
||||
|
||||
namespace langguanApi.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// 缓存管理
|
||||
/// </summary>
|
||||
[ServiceInjection(InjectionType.Singleton)]
|
||||
public class CacheManager
|
||||
{
|
||||
private readonly IDatabase _redisDatabase;
|
||||
public CacheManager(RedisHelper redisHelper)
|
||||
{
|
||||
_redisDatabase = redisHelper._database;
|
||||
}
|
||||
/// <summary>
|
||||
/// 缓存数据
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="dataFetcher"></param>
|
||||
/// <param name="seconds">缓存时间秒,0=int.max ,</param>
|
||||
/// <returns></returns>
|
||||
public async Task<T> GetConvertVale<T>(string cacheKey, Func<Task<T>> dataFetcher, int seconds = 0)
|
||||
{
|
||||
var cacheData = await _redisDatabase.StringGetAsync(cacheKey);
|
||||
if (cacheData.IsNull)
|
||||
{
|
||||
var temp = await dataFetcher();
|
||||
cacheData = JsonConvert.SerializeObject(temp);
|
||||
seconds = seconds == 0 ? int.MaxValue : seconds;
|
||||
await _redisDatabase.StringSetAsync(cacheKey, cacheData, TimeSpan.FromSeconds(seconds), When.NotExists);
|
||||
return temp;
|
||||
}
|
||||
return JsonConvert.DeserializeObject<T>(cacheData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using StackExchange.Redis;
|
||||
|
||||
namespace langguanApi.Common.Redis
|
||||
{
|
||||
public class RedisHelper
|
||||
{
|
||||
public IDatabase _database;
|
||||
/// <summary>
|
||||
/// sub
|
||||
/// </summary>
|
||||
public ISubscriber _subscriber;
|
||||
public RedisHelper()
|
||||
{
|
||||
// var con = RedisOptions.Default.GetConnect();
|
||||
IConnectionMultiplexer connection = ConnectionMultiplexer.Connect(RedisOptions.Default.GetConnect());
|
||||
_subscriber = connection.GetSubscriber();
|
||||
_database = connection.GetDatabase(RedisOptions.Default.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
namespace langguanApi.Common.Redis
|
||||
{
|
||||
public class RedisKeylist
|
||||
{
|
||||
public static string UserLoginInfo = "UserLoginInfo";
|
||||
/// <summary>
|
||||
/// 缓存天气信息
|
||||
/// </summary>
|
||||
public static string Weather = "weather";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
namespace langguanApi.Common.Redis
|
||||
{
|
||||
public class RedisOptions
|
||||
{
|
||||
public static readonly RedisOptions Default = new RedisOptions();
|
||||
public RedisOptions()
|
||||
{
|
||||
this.Server = null;
|
||||
this.Port = 6379;
|
||||
this.Password = null;
|
||||
this.Key = null;
|
||||
this.Index = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// redis 服务地址
|
||||
/// </summary>
|
||||
public string Server { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// redis 端口
|
||||
/// </summary>
|
||||
public int Port { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// redis 连接密码
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自定义Key
|
||||
/// </summary>
|
||||
public string Key { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认数据库索引
|
||||
/// </summary>
|
||||
public int Index { get; set; }
|
||||
public string Connection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 转换数据库连接字符串
|
||||
/// </summary>
|
||||
/// <param name="node"></param>
|
||||
/// <returns></returns>
|
||||
public string GetConnect()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Password))
|
||||
return $"{Server}";
|
||||
else
|
||||
return $"{Server},password={Password}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
using langguanApi.Model;
|
||||
using langguanApi.Model.Dto;
|
||||
using langguanApi.Service;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace langguanApi.Controllers
|
||||
{
|
||||
[Route("api/[controller]/[action]")]
|
||||
[ApiController]
|
||||
public class DeviceController : ControllerBase
|
||||
{
|
||||
private readonly DeviceService _deviceService;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="deviceService"></param>
|
||||
public DeviceController(DeviceService deviceService)
|
||||
{
|
||||
_deviceService = deviceService;
|
||||
}
|
||||
/// <summary>
|
||||
/// 列表
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Getpage([FromQuery] reqpage input)
|
||||
{
|
||||
var result = await _deviceService.GetPage(input);
|
||||
return Ok(result);
|
||||
}
|
||||
/// <summary>
|
||||
///新加
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Addd([FromBody] DeviceDto input)
|
||||
{
|
||||
var result = await _deviceService.Add(input);
|
||||
return Ok(result);
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public async Task<IActionResult> Remove(IEnumerable<string> ids)
|
||||
{
|
||||
var result = await _deviceService.remove(ids);
|
||||
return Ok(result);
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
public async Task<IActionResult> update([FromBody] DeviceDto input)
|
||||
{
|
||||
var result = await _deviceService.update(input);
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using langguanApi.Service;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace langguanApi.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class HJ212Controller : ControllerBase
|
||||
{
|
||||
private readonly Hj212Service _hj212Service;
|
||||
|
||||
public HJ212Controller(Hj212Service hj212Service)
|
||||
{
|
||||
_hj212Service = hj212Service;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定设备的历史数据
|
||||
/// </summary>
|
||||
/// <param name="mn"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Get(string mn)
|
||||
{
|
||||
var resul = await _hj212Service.GetViewByDeviceMn(mn);
|
||||
return Ok(resul);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
using langguanApi.Model;
|
||||
using langguanApi.Service;
|
||||
using langguanApi.Service.HJ212;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text;
|
||||
|
||||
namespace langguanApi.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class HomeController : ControllerBase
|
||||
{
|
||||
private readonly HomeService _homeService;
|
||||
public HomeController(HomeService homeService)
|
||||
{
|
||||
_homeService = homeService;
|
||||
}
|
||||
/// <summary>
|
||||
/// 首页view
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("view")]
|
||||
public async Task<IActionResult> View()
|
||||
{
|
||||
return Ok( await _homeService.View() );
|
||||
|
||||
}
|
||||
[HttpGet("test")]
|
||||
/// <summary>
|
||||
/// test
|
||||
/// </summary>
|
||||
/// <param name="num">数字</param>
|
||||
/// <param name="key">字符串</param>
|
||||
/// <returns></returns>
|
||||
public async Task<IActionResult> test(int num = 1, string key = "")
|
||||
{
|
||||
// string rawText = "数据报:##0250QN=20240424224800000;ST=22;CN=2011;PW=123456;MN=LGYC022024690001;Flag=5;CP=&&DataTime=20240424224800;a34001-Rtd=356.2";
|
||||
//NetPackage netPackage = NetPackage.Parse(rawText, null);
|
||||
//((NetServer)Server).RaiseReceivedData(this, netPackage, rawText);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:6.0-alpine AS base
|
||||
WORKDIR /app
|
||||
EXPOSE 80
|
||||
|
||||
#FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
|
||||
#WORKDIR /src
|
||||
#COPY ["langguanApi/langguanApi.csproj", "langguanApi/"]
|
||||
#RUN dotnet restore "langguanApi/langguanApi.csproj"
|
||||
COPY . .
|
||||
#WORKDIR "/src/langguanApi"
|
||||
#RUN dotnet build "langguanApi.csproj" -c Release -o /app/build
|
||||
#
|
||||
#FROM build AS publish
|
||||
#RUN dotnet publish "langguanApi.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||
#
|
||||
#FROM base AS final
|
||||
#WORKDIR /app
|
||||
#COPY --from=publish /app/publish .
|
||||
ENTRYPOINT ["dotnet", "langguanApi.dll"]
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
namespace langguanApi.Extensions.AutoDI
|
||||
{
|
||||
/// <summary>
|
||||
/// 注入生命周期
|
||||
/// </summary>
|
||||
public enum InjectionType
|
||||
{
|
||||
/// <summary>
|
||||
/// Transient
|
||||
/// </summary>
|
||||
Transient,
|
||||
|
||||
/// <summary>
|
||||
/// Scoped
|
||||
/// </summary>
|
||||
Scoped,
|
||||
|
||||
/// <summary>
|
||||
/// Singleton
|
||||
/// </summary>
|
||||
Singleton
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
namespace langguanApi.Extensions.AutoDI
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class ServiceInjectionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Type InterfaceType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 注入类型
|
||||
/// </summary>
|
||||
public InjectionType InjectionType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务注入
|
||||
/// </summary>
|
||||
public ServiceInjectionAttribute()
|
||||
{
|
||||
InjectionType = InjectionType.Scoped;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务注入
|
||||
/// </summary>
|
||||
/// <param name="injectionType">注入类型</param>
|
||||
public ServiceInjectionAttribute(InjectionType injectionType)
|
||||
{
|
||||
InjectionType = injectionType;
|
||||
}
|
||||
/// <summary>
|
||||
/// 服务注入
|
||||
/// </summary>
|
||||
/// <param name="interfaceType">服务的接口类型</param>
|
||||
/// <param name="injectionType">注入的类型</param>
|
||||
public ServiceInjectionAttribute(Type interfaceType, InjectionType injectionType)
|
||||
{
|
||||
InterfaceType = interfaceType;
|
||||
InjectionType = injectionType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
using System.Reflection;
|
||||
|
||||
namespace langguanApi.Extensions.AutoDI
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动注入
|
||||
/// </summary>
|
||||
public static class AutoDIExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection ServicesAutoInjectionExtension(this IServiceCollection serviceCollection)
|
||||
{
|
||||
var directory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var types = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly)
|
||||
.Select(Assembly.LoadFrom)
|
||||
.SelectMany(a => a.GetTypes());
|
||||
Injection(serviceCollection, types);
|
||||
return serviceCollection;
|
||||
}
|
||||
/// <summary>
|
||||
/// 服务自动注入
|
||||
/// </summary>
|
||||
/// <param name="serviceCollection">需要自动注入服务的服务集合</param>
|
||||
/// <param name="selector">应用于每个Assembly的筛选函数</param>
|
||||
/// <exception cref="ArgumentOutOfRangeException">指定的注入类型不在可注入的范围内</exception>
|
||||
/// <exception cref="NoImplementationInterfaceException">指定注入的类型未实现任何服务</exception>
|
||||
/// <exception cref="ArgumentException">输入的参数错误:1、注入的类型未实现指定的服务。2、指定的服务不是Interface类型</exception>
|
||||
/// <returns>自动注入服务后的服务集合</returns>
|
||||
public static IServiceCollection ServicesAutoInjection(this IServiceCollection serviceCollection, Func<Assembly, bool> selector)
|
||||
{
|
||||
var directory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var types = Directory.GetFiles(directory, "*.dll", SearchOption.TopDirectoryOnly)
|
||||
.Select(Assembly.LoadFrom)
|
||||
.Where(selector)
|
||||
.SelectMany(a => a.GetTypes());
|
||||
|
||||
Injection(serviceCollection, types);
|
||||
|
||||
return serviceCollection;
|
||||
}
|
||||
// 注入逻辑
|
||||
private static void Injection(IServiceCollection serviceCollection, IEnumerable<Type> types)
|
||||
{
|
||||
foreach (var type in types)
|
||||
{
|
||||
var attribute = type.GetCustomAttribute<ServiceInjectionAttribute>();
|
||||
if (attribute == null) continue;
|
||||
switch (attribute.InjectionType)
|
||||
{
|
||||
case InjectionType.Transient:
|
||||
serviceCollection.AddTransient(type);
|
||||
break;
|
||||
case InjectionType.Scoped:
|
||||
serviceCollection.AddScoped(type);
|
||||
break;
|
||||
case InjectionType.Singleton:
|
||||
serviceCollection.AddSingleton(type);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using langguanApi.Common.Redis;
|
||||
|
||||
namespace langguanApi.Extensions
|
||||
{
|
||||
public static class RedisExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// add redis service
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <param name="redisOptions"></param>
|
||||
public static void AddRedis(this IServiceCollection services, Action<RedisOptions> redisOptions)
|
||||
{
|
||||
services.AddSingleton<RedisHelper>();
|
||||
if (redisOptions != null)
|
||||
{
|
||||
redisOptions.Invoke(RedisOptions.Default);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using langguanApi.Service;
|
||||
|
||||
namespace langguanApi.Extensions
|
||||
{
|
||||
public static class SocketExtension
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
public static void AddSocketService(this IServiceCollection services)
|
||||
{
|
||||
// services.AddSingleton<MQTTService>();
|
||||
services.AddTransient<HJ212SocketServer>();
|
||||
services.AddTransient<PingService>();
|
||||
|
||||
IServiceProvider serviceProvider = services.BuildServiceProvider();
|
||||
_ = serviceProvider.GetService<HJ212SocketServer>().Start();
|
||||
serviceProvider.GetService<PingService>().CreatTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace langguanApi.Middleware
|
||||
{
|
||||
public class CustomerExceptionFilter : IAsyncExceptionFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// 日志
|
||||
/// </summary>
|
||||
public ILogger _logger;
|
||||
/// <summary>
|
||||
/// 构参
|
||||
/// </summary>
|
||||
/// <param name="loggerFactory"></param>
|
||||
public CustomerExceptionFilter(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<CustomerExceptionFilter>();
|
||||
}
|
||||
/// <summary>
|
||||
/// 重写
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns></returns>
|
||||
public Task OnExceptionAsync(ExceptionContext context)
|
||||
{
|
||||
if (context.ExceptionHandled == false)
|
||||
{
|
||||
var json = new { cdoe = -1, msg = context.Exception.Message, data = context.Exception.Data };
|
||||
context.HttpContext.Response.StatusCode = 400;
|
||||
context.Result = new JsonResult(json);
|
||||
}
|
||||
_logger.LogError($"请求出现异常,地址:{context.HttpContext?.Request?.Path},请求方式:{context.HttpContext.Request.Method},异常信息:{context.Exception.Message}");
|
||||
//记录异常已经处理
|
||||
context.ExceptionHandled = true;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
public class Alert : BaseModel
|
||||
{
|
||||
public string DeviceMn { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// Api返回结果
|
||||
/// </summary>
|
||||
public class ApiResult
|
||||
{
|
||||
/// <summary>
|
||||
/// code=0成功。1失败
|
||||
/// </summary>
|
||||
public int code { get; set; } = 0;
|
||||
/// <summary>
|
||||
/// 结果
|
||||
/// </summary>
|
||||
public object data { get; set; }
|
||||
/// <summary>
|
||||
/// 消息
|
||||
/// </summary>
|
||||
public string msg { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// base model
|
||||
/// </summary>
|
||||
public class BaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// //标记主键
|
||||
/// </summary>
|
||||
[BsonId]
|
||||
[BsonRepresentation(BsonType.ObjectId)] //参数类型 , 无需赋值
|
||||
public string Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// //指明数据库中字段名为CreateDateTime
|
||||
/// </summary>
|
||||
[BsonElement(nameof(CreateDateTime))] //指明数据库中字段名为CreateDateTime
|
||||
|
||||
public DateTime CreateDateTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标记删除
|
||||
/// </summary>
|
||||
//[BsonElement(nameof(IsDelete))]
|
||||
public bool IsDelete { get; set; }=false;
|
||||
|
||||
/// <summary>
|
||||
/// basemodel
|
||||
/// </summary>
|
||||
public BaseModel()
|
||||
{
|
||||
CreateDateTime = DateTime.Now;
|
||||
IsDelete = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 命令编码
|
||||
/// </summary>
|
||||
public enum CommandNumber
|
||||
{
|
||||
/// <summary>
|
||||
/// 心跳包
|
||||
/// </summary>
|
||||
HeartbeatPackage = 1062,
|
||||
|
||||
/// <summary>
|
||||
/// 工控机向上位机上传分钟数据
|
||||
/// </summary>
|
||||
UploadMinuteData = 2051,
|
||||
|
||||
/// <summary>
|
||||
/// 工控机向上位机上传小时数据
|
||||
/// </summary>
|
||||
UploadHourlyData = 2061,
|
||||
|
||||
/// <summary>
|
||||
/// 工控机向上位机上传日数据
|
||||
/// </summary>
|
||||
UploadDailyData = 2031,
|
||||
|
||||
/// <summary>
|
||||
/// 工控机向上位机上传实时数据
|
||||
/// </summary>
|
||||
UploadRealTimeData = 2011,
|
||||
|
||||
/// <summary>
|
||||
/// 上位机向工控机返回应答
|
||||
/// </summary>
|
||||
DataResponse = 9014
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
using IceCoffee.Common.Extensions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// CP指令
|
||||
/// </summary>
|
||||
public class CpCommand
|
||||
{
|
||||
public ResponseCode ExeRtn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据时间信息
|
||||
/// </summary>
|
||||
public DateTime DataTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 污染物信息
|
||||
/// </summary>
|
||||
public List<PollutantInfo> PollutantInfo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 解析
|
||||
/// </summary>
|
||||
/// <param name="cp"></param>
|
||||
/// <returns></returns>
|
||||
public static CpCommand Parse(string cp)
|
||||
{
|
||||
var cpCommand = new CpCommand();
|
||||
|
||||
cpCommand.PollutantInfo = new List<PollutantInfo>();
|
||||
|
||||
cpCommand.DataTime = DateTime.ParseExact(cp.GetMidStr("DataTime=", ";"), "yyyyMMddHHmmss", null);
|
||||
cp = cp.Substring(24);
|
||||
foreach (string project in cp.Split(';', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
var pollutantInfo = new PollutantInfo();
|
||||
|
||||
string[] classes = project.Split(',');
|
||||
foreach (string @class in classes)
|
||||
{
|
||||
string[] keyValue = @class.Split('=');
|
||||
string key = keyValue[0];
|
||||
string value = keyValue[1];
|
||||
|
||||
string[] factorCodeType = key.Split('-');
|
||||
string factorCode = factorCodeType[0];
|
||||
string type = factorCodeType[1];
|
||||
|
||||
pollutantInfo.FactorCode = (FactorCode)Enum.Parse(typeof(FactorCode), factorCode);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case nameof(Model.PollutantInfo.Rtd):
|
||||
if (string.IsNullOrEmpty(value) == false && decimal.TryParse(value, out decimal rtd))
|
||||
{
|
||||
pollutantInfo.Rtd = rtd;
|
||||
}
|
||||
break;
|
||||
case nameof(Model.PollutantInfo.Avg):
|
||||
if (string.IsNullOrEmpty(value) == false && decimal.TryParse(value, out decimal avg))
|
||||
{
|
||||
pollutantInfo.Avg = avg;
|
||||
}
|
||||
break;
|
||||
case nameof(Model.PollutantInfo.Max):
|
||||
if (string.IsNullOrEmpty(value) == false && decimal.TryParse(value, out decimal max))
|
||||
{
|
||||
pollutantInfo.Max = max;
|
||||
}
|
||||
break;
|
||||
case nameof(Model.PollutantInfo.Min):
|
||||
if (string.IsNullOrEmpty(value) == false && decimal.TryParse(value, out decimal min))
|
||||
{
|
||||
pollutantInfo.Min = min;
|
||||
}
|
||||
break;
|
||||
case nameof(Model.PollutantInfo.Cou):
|
||||
if (string.IsNullOrEmpty(value) == false && decimal.TryParse(value, out decimal cou))
|
||||
{
|
||||
pollutantInfo.Cou = cou;
|
||||
}
|
||||
break;
|
||||
case nameof(Model.PollutantInfo.Flag):
|
||||
pollutantInfo.Flag = (InstrumentationDataFlag)Enum.Parse(typeof(InstrumentationDataFlag), value);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("无效的CP指令字段名");
|
||||
}
|
||||
}
|
||||
|
||||
cpCommand.PollutantInfo.Add(pollutantInfo);
|
||||
}
|
||||
|
||||
return cpCommand;
|
||||
//}
|
||||
//catch (Exception ex)
|
||||
//{
|
||||
// Console.WriteLine($"Error in CpCommand.Parse:{ex.Message}");
|
||||
// throw new Exception("Error in CpCommand.Parse", ex);
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string Serialize()
|
||||
{
|
||||
return "ExeRtn=" + (int)ExeRtn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
using IceCoffee.Common.Extensions;
|
||||
using System.Text;
|
||||
|
||||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据段
|
||||
/// </summary>
|
||||
public class DataSegment
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认应答系统编码
|
||||
/// </summary>
|
||||
public const string ResponseST = "91";
|
||||
|
||||
/// <summary>
|
||||
/// 请求编号
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// yyyyMMddHHmmssZZZ 取当前系统时间, 精确到毫秒值, 用来唯一标识一次命令交互
|
||||
/// </remarks>
|
||||
public string QN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 系统编号
|
||||
/// </summary>
|
||||
public string ST { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 命令编码
|
||||
/// <para>详见附录 2</para>
|
||||
/// </summary>
|
||||
public CommandNumber CN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 访问密码
|
||||
/// <para>对接时提供给各个对接站点</para>
|
||||
/// </summary>
|
||||
public string PW { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 设备唯一标识
|
||||
/// <para>对接时提供给各个对接站点</para>
|
||||
/// </summary>
|
||||
public string MN { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 拆分包及应答标志
|
||||
/// </summary>
|
||||
public PackageFlag PackageFlag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 总包数
|
||||
/// <para>PNUM 指示本次通讯中总共包含的包数,注:不分包时可以没有本字段,与标志位有关</para>
|
||||
/// </summary>
|
||||
public int PNUM { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 包号
|
||||
/// <para>PNO 指示当前数据包的包号,注: 不分包时可以没有本字段,与标志位有关</para>
|
||||
/// </summary>
|
||||
public int PNO { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 指令
|
||||
/// <para>CP=&&数据区&&( 详见表 5 )</para>
|
||||
/// </summary>
|
||||
public CpCommand CpCommand { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 解析
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="unpackCacheFunc"></param>
|
||||
/// <returns></returns>
|
||||
public static DataSegment Parse(string data, Func<StringBuilder> unpackCacheFunc)
|
||||
{
|
||||
DataSegment dataSegment = new DataSegment();
|
||||
try
|
||||
{
|
||||
int outEnd;
|
||||
dataSegment.QN = data.GetMidStr("QN=", ";", out outEnd);
|
||||
|
||||
if (outEnd < 0)
|
||||
{
|
||||
outEnd = 0;
|
||||
}
|
||||
|
||||
dataSegment.ST = data.GetMidStr("ST=", ";", out outEnd, outEnd);
|
||||
dataSegment.CN = (CommandNumber)int.Parse(data.GetMidStr("CN=", ";", out outEnd, outEnd));
|
||||
dataSegment.PW = data.GetMidStr("PW=", ";", out outEnd, outEnd);
|
||||
dataSegment.MN = data.GetMidStr("MN=", ";", out outEnd, outEnd);
|
||||
|
||||
string packageFlag = data.GetMidStr("Flag=", ";", out outEnd, outEnd);
|
||||
if (string.IsNullOrEmpty(packageFlag) || int.TryParse(packageFlag, out _) == false || outEnd < 0)
|
||||
{
|
||||
outEnd = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dataSegment.PackageFlag = PackageFlag.Parse(packageFlag);
|
||||
}
|
||||
|
||||
if (dataSegment.PackageFlag != null && dataSegment.PackageFlag.D == 1)
|
||||
{
|
||||
// 分包
|
||||
dataSegment.PNUM = int.Parse(data.GetMidStr("PNUM=", ";", out outEnd, outEnd));
|
||||
dataSegment.PNO = int.Parse(data.GetMidStr("PNO=", ";", out outEnd, outEnd));
|
||||
|
||||
string cp = data.GetMidStr("CP=&&", "&&", out outEnd, outEnd);
|
||||
var cache = unpackCacheFunc.Invoke();
|
||||
if (dataSegment.PNO == 1)// 第一个包
|
||||
{
|
||||
cache.Append(cp);
|
||||
}
|
||||
else if (dataSegment.PNUM == dataSegment.PNO)// 最后一个包
|
||||
{
|
||||
cache.Append(cp.Substring(23));
|
||||
dataSegment.CpCommand = CpCommand.Parse(cache.ToString());
|
||||
cache.Clear();
|
||||
}
|
||||
else// 中间的包
|
||||
{
|
||||
cache.Append(cp.Substring(23));// 23 - DataTime=20170920100000; 留分号
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string cp = data.GetMidStr("CP=&&", "&&", out outEnd, outEnd);
|
||||
// 过滤心跳包
|
||||
dataSegment.CpCommand = dataSegment.CN == CommandNumber.HeartbeatPackage ? new CpCommand() : CpCommand.Parse(cp);
|
||||
}
|
||||
return dataSegment;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error in DataSegment.Parse:{ex.Message}");
|
||||
|
||||
}
|
||||
return dataSegment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string Serialize()
|
||||
{
|
||||
return $"QN={QN};ST={ST};CN={(int)CN};PW={PW};MN={MN};Flag={PackageFlag.Serialize()};CP=&&{CpCommand.Serialize()}&&";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备信息
|
||||
/// </summary>
|
||||
public class Device : BaseModel
|
||||
{
|
||||
public string deviceMN { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Ip { get; set; }
|
||||
public double lng { get; set; }
|
||||
public double lat { get; set; }
|
||||
public string desricption { get; set; }
|
||||
public int state { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
namespace langguanApi.Model.Dto
|
||||
{
|
||||
public class DeviceDto
|
||||
{
|
||||
public string deviceMN { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Ip { get; set; }
|
||||
public double lng { get; set; }
|
||||
public double lat { get; set; }
|
||||
public string desricption { get; set; }
|
||||
public int state { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
using System.Text;
|
||||
|
||||
namespace langguanApi.Model.Dto
|
||||
{
|
||||
/// <summary>
|
||||
/// HJ212_2017
|
||||
/// </summary>
|
||||
public class HJ212_2017
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据帧头
|
||||
/// </summary>
|
||||
public string header { get; set; }
|
||||
/// <summary>
|
||||
/// 数据长度
|
||||
/// </summary>
|
||||
public string data_length { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据头
|
||||
/// </summary>
|
||||
public Dictionary<string, string> DATA_HEAD { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public Dictionary<string, string> CP { get; set; }
|
||||
/// <summary>
|
||||
/// CRC校验
|
||||
/// </summary>
|
||||
public string CRC { get; set; }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="Text"></param>
|
||||
/// <returns></returns>
|
||||
public bool DecodeData(string Text)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Text.Length < 12 || !Text.StartsWith("##"))
|
||||
{
|
||||
Console.WriteLine("不是HJ212协议的报文!");
|
||||
return false;
|
||||
}
|
||||
Console.WriteLine($"开始解码数据:");
|
||||
Text = Text.ToUpper().Replace(";CP=", "").Replace(" ", "");//有些厂家协议不很标准,有的大小写不一致,此处强制转大写字母
|
||||
header = Text.Substring(0, 2);
|
||||
data_length = Text.Substring(2, 4);
|
||||
string[] data_0 = Text.Substring(6, Text.Length - 6).Split(new char[] { '&', '&' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] data_1 = data_0[0].Split(new char[] { ';' });
|
||||
DATA_HEAD = new Dictionary<string, string>();
|
||||
for (int h = 0; h < data_1.Length; h++)
|
||||
{
|
||||
string[] d_1 = data_1[h].Split(new char[] { '=' });
|
||||
DATA_HEAD.Add(d_1[0], d_1[1]);
|
||||
}
|
||||
string[] data_2 = data_0[1].Split(new char[] { ';' });
|
||||
CP = new Dictionary<string, string>();
|
||||
for (int i = 0; i < data_2.Length; i++)
|
||||
{
|
||||
string[] d_6 = data_2[i].Split(new char[] { ',' });
|
||||
for (int j = 0; j < d_6.Length; j++)
|
||||
{
|
||||
string[] d_7 = d_6[j].Split(new char[] { '=' });
|
||||
CP.Add(d_7[0].Replace("-RTD", ""), d_7[1]);
|
||||
}
|
||||
}
|
||||
CRC = data_0[2];
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//数据接收不完整
|
||||
Console.WriteLine($" 解码失败:err:{ex},数据有问题," + Text);
|
||||
//throw;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 判断数据是否通过校验
|
||||
/// </summary>
|
||||
/// <param name="Text">原始数据</param>
|
||||
/// <returns>是否通过</returns>
|
||||
public bool Crc16(string Text)
|
||||
{
|
||||
try
|
||||
{
|
||||
string CRC = Text.Substring(Text.Length - 4, 4);
|
||||
|
||||
Text = Text.Substring(Text.IndexOf("QN"));
|
||||
Text = Text.Substring(0, Text.Length - 4);
|
||||
|
||||
byte[] bytes = Encoding.ASCII.GetBytes(Text);
|
||||
int crcRegister = 0xFFFF;
|
||||
for (int i = 0; i < bytes.Length; i++)
|
||||
{
|
||||
crcRegister = (crcRegister >> 8) ^ bytes[i];
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
int check = crcRegister & 0x0001;
|
||||
crcRegister >>= 1;
|
||||
if (check == 0x0001)
|
||||
{
|
||||
crcRegister ^= 0xA001;
|
||||
}
|
||||
}
|
||||
}
|
||||
string result = string.Format("{0:X}", crcRegister);//转十六进制
|
||||
for (int i = result.Length; i < 4; i++)//补足 4 位
|
||||
{
|
||||
result = "0" + result;
|
||||
}
|
||||
//LogApi.WriteLog("计算校验码:" + result);
|
||||
if (result == CRC)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("校验码有误," + CRC);
|
||||
Console.WriteLine("待校验数据:" + Text);
|
||||
Console.WriteLine("计算校验码:" + result);
|
||||
//LogApi.WriteLog("校验码有误:" + CRC);
|
||||
//LogApi.WriteLog("待校验数据:" + Text);
|
||||
//LogApi.WriteLog("计算校验码:" + result);
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Console.WriteLine("数据校验:数据有问题:" + Text);
|
||||
//数据接收不完整
|
||||
return false;
|
||||
//throw;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 污染物因子编码
|
||||
/// </summary>
|
||||
public enum FactorCode
|
||||
{
|
||||
#region VOCs 在线检测仪因子编码
|
||||
a24901,
|
||||
a24904,
|
||||
a24905,
|
||||
a24042,
|
||||
a25002,
|
||||
a24036,
|
||||
a24908,
|
||||
a24909,
|
||||
a24910,
|
||||
a24012,
|
||||
a24043,
|
||||
a24084,
|
||||
a24911,
|
||||
a25003,
|
||||
a24912,
|
||||
a24913,
|
||||
a24070,
|
||||
a25004,
|
||||
a25008,
|
||||
a25038,
|
||||
a25006,
|
||||
a24044,
|
||||
a25034,
|
||||
a25033,
|
||||
a25902,
|
||||
a25014,
|
||||
a25021,
|
||||
a25901,
|
||||
a25019,
|
||||
a24068,
|
||||
a25020,
|
||||
a25903,
|
||||
a25904,
|
||||
a24914,
|
||||
a24915,
|
||||
a24001,
|
||||
a24045,
|
||||
a24002,
|
||||
a24053,
|
||||
a24038,
|
||||
a24037,
|
||||
a24079,
|
||||
a24064,
|
||||
a24919,
|
||||
a24063,
|
||||
a24902,
|
||||
a24041,
|
||||
a24039,
|
||||
a24077,
|
||||
a24074,
|
||||
a24076,
|
||||
a24907,
|
||||
a24903,
|
||||
a24011,
|
||||
a24061,
|
||||
a24906,
|
||||
a31002,
|
||||
a31005,
|
||||
|
||||
#region 甲烷和非甲烷总烃分析仪因子编码
|
||||
a05002,
|
||||
a99999,
|
||||
a24088,
|
||||
#endregion
|
||||
|
||||
a24072,
|
||||
a05009,
|
||||
a05014,
|
||||
a24099,
|
||||
a24058,
|
||||
a24046,
|
||||
a24078,
|
||||
a24008,
|
||||
a24015,
|
||||
a24916,
|
||||
a31004,
|
||||
a31003,
|
||||
a24047,
|
||||
a05013,
|
||||
a31024,
|
||||
a99009,
|
||||
a24003,
|
||||
a28006,
|
||||
a31015,
|
||||
a24016,
|
||||
a31900,
|
||||
a24111,
|
||||
a24004,
|
||||
a24018,
|
||||
a24005,
|
||||
a24017,
|
||||
a24049,
|
||||
a24917,
|
||||
a24027,
|
||||
a31010,
|
||||
a31026,
|
||||
a24007,
|
||||
a24112,
|
||||
a24054,
|
||||
a24019,
|
||||
a24050,
|
||||
a31009,
|
||||
a24034,
|
||||
a25010,
|
||||
a24009,
|
||||
a24020,
|
||||
a25012,
|
||||
a25011,
|
||||
a30003,
|
||||
a30008,
|
||||
a99051,
|
||||
a29026,
|
||||
a29017,
|
||||
a31025,
|
||||
a24110,
|
||||
a25072,
|
||||
a29015,
|
||||
a31030,
|
||||
a31027,
|
||||
a24006,
|
||||
a25013,
|
||||
a25068,
|
||||
a25015,
|
||||
a24113,
|
||||
a25059,
|
||||
a31001,
|
||||
a31016,
|
||||
a31018,
|
||||
a31020,
|
||||
a24102,
|
||||
a30001,
|
||||
a25905,
|
||||
a24918,
|
||||
a28900,
|
||||
a28010,
|
||||
a30002,
|
||||
a30023,
|
||||
a28001,
|
||||
a24059,
|
||||
a24944,
|
||||
#endregion
|
||||
|
||||
#region 气象五参数在线监测仪因子编码
|
||||
a01030,
|
||||
a01004,
|
||||
a01007,
|
||||
a01008,
|
||||
a06001,
|
||||
a01001,
|
||||
#endregion
|
||||
|
||||
#region 氮氧化物分析仪
|
||||
a21003,
|
||||
a21004,
|
||||
a21002,
|
||||
a21029,
|
||||
#endregion
|
||||
|
||||
#region 常规六参因子编码
|
||||
a34004,
|
||||
a34002,
|
||||
a21026,
|
||||
// a21004,
|
||||
a21005,
|
||||
#endregion
|
||||
|
||||
#region 在线离子色谱仪因子编码
|
||||
a06010,
|
||||
a06011,
|
||||
a06013,
|
||||
a06009,
|
||||
a06012,
|
||||
a06005,
|
||||
a06006,
|
||||
a06019,
|
||||
a06008,
|
||||
a21001,
|
||||
a20109,
|
||||
// a21026,
|
||||
a20110,
|
||||
a21024,
|
||||
// a21004,
|
||||
a06007,
|
||||
a06015,
|
||||
a06018,
|
||||
a06021,
|
||||
a06017,
|
||||
a06022,
|
||||
a06023,
|
||||
a06024,
|
||||
a06025,
|
||||
a06026,
|
||||
a06027,
|
||||
a06028,
|
||||
a06029,
|
||||
a06030,
|
||||
a06031,
|
||||
a06032,
|
||||
a06033,
|
||||
a34007,
|
||||
a34006,
|
||||
a34047,
|
||||
a34048,
|
||||
a34049,
|
||||
a20044,
|
||||
a20072,
|
||||
a20058,
|
||||
a20033,
|
||||
a20026,
|
||||
a20104,
|
||||
a20041,
|
||||
a20064,
|
||||
a20111,
|
||||
a20055,
|
||||
a20095,
|
||||
a20004,
|
||||
a20092,
|
||||
a20101,
|
||||
a20012,
|
||||
a20007,
|
||||
a20029,
|
||||
a20068,
|
||||
a20038,
|
||||
a20061,
|
||||
a20112,
|
||||
a20113,
|
||||
a20089,
|
||||
a20114,
|
||||
a20115,
|
||||
a20086,
|
||||
a20116,
|
||||
a20117,
|
||||
a20118,
|
||||
a20119,
|
||||
a20079,
|
||||
a20120,
|
||||
a20002,
|
||||
a20121,
|
||||
a20075,
|
||||
a20052,
|
||||
a20122,
|
||||
a20123,
|
||||
a21012,
|
||||
a20124,
|
||||
a20107,
|
||||
a20125,
|
||||
a20126,
|
||||
a20127,
|
||||
a20128,
|
||||
a20129,
|
||||
a20098,
|
||||
a20020,
|
||||
a01031,
|
||||
a01032,
|
||||
a01029,
|
||||
a01033,
|
||||
a01034,
|
||||
a01035,
|
||||
a01036,
|
||||
a01037,
|
||||
// a01001,
|
||||
// a01004,
|
||||
a01038,
|
||||
a01039,
|
||||
// a06001,
|
||||
a01022,
|
||||
a01023,
|
||||
// a34002,
|
||||
// a34004,
|
||||
a01024,
|
||||
a19006,
|
||||
a01025,
|
||||
a01026,
|
||||
a01020,
|
||||
a01027,
|
||||
a01028,
|
||||
// a01029,
|
||||
// a01022,
|
||||
// a01023,
|
||||
a05024,
|
||||
a19999,
|
||||
a19998,
|
||||
a19997,
|
||||
a19996,
|
||||
a19995,
|
||||
a19994,
|
||||
a19993,
|
||||
#endregion
|
||||
|
||||
#region 气监测因子编码表(引用 HJ 524-2009)
|
||||
a00000,
|
||||
//a01001,
|
||||
a01002,
|
||||
a01006,
|
||||
//a01007,
|
||||
//a01008,
|
||||
a01010,
|
||||
a01011,
|
||||
a01012,
|
||||
a01013,
|
||||
a01014,
|
||||
a01015,
|
||||
a01016,
|
||||
a01017,
|
||||
a01901,
|
||||
a01902,
|
||||
a05001,
|
||||
//a05002,
|
||||
a05008,
|
||||
//a05009,
|
||||
//a05013,
|
||||
a19001,
|
||||
//a20007,
|
||||
a20016,
|
||||
a20025,
|
||||
//a20026,
|
||||
a20043,
|
||||
//a20044,
|
||||
a20057,
|
||||
//a20058,
|
||||
a20063,
|
||||
a20091,
|
||||
//a21001,
|
||||
//a21002,
|
||||
//a21003,
|
||||
//a21004,
|
||||
//a21005,
|
||||
a21017,
|
||||
a21018,
|
||||
a21022,
|
||||
//a21024,
|
||||
//a21026,
|
||||
a21028,
|
||||
a23001,
|
||||
//a24003,
|
||||
//a24004,
|
||||
//a24005,
|
||||
//a24006,
|
||||
//a24007,
|
||||
//a24008,
|
||||
//a24009,
|
||||
//a24015,
|
||||
//a24016,
|
||||
//a24017,
|
||||
//a24018,
|
||||
//a24019,
|
||||
//a24020,
|
||||
//a24027,
|
||||
//a24034,
|
||||
//a24036,
|
||||
//a24042,
|
||||
//a24043,
|
||||
//a24046,
|
||||
//a24047,
|
||||
//a24049,
|
||||
//a24050,
|
||||
//a24053,
|
||||
//a24054,
|
||||
//a24072,
|
||||
//a24078,
|
||||
a24087,
|
||||
//a24088,
|
||||
//a24099,
|
||||
//a24110,
|
||||
//a24111,
|
||||
//a24112,
|
||||
//a24113,
|
||||
//a25002,
|
||||
//a25003,
|
||||
//a25004,
|
||||
a25005,
|
||||
//a25006,
|
||||
a25007,
|
||||
//a25008,
|
||||
//a25010,
|
||||
//a25011,
|
||||
//a25012,
|
||||
//a25013,
|
||||
//a25014,
|
||||
//a25015,
|
||||
//a25019,
|
||||
//a25020,
|
||||
//a25021,
|
||||
a25023,
|
||||
//a25038,
|
||||
a25044,
|
||||
//a25072,
|
||||
a26001,
|
||||
//a29017,
|
||||
//a29026,
|
||||
//a30001,
|
||||
//a30008,
|
||||
a30022,
|
||||
//a31001,
|
||||
//a31002,
|
||||
//a31024,
|
||||
//a31025,
|
||||
//a31030,
|
||||
a34001,
|
||||
//a34002,
|
||||
//a34004,
|
||||
a34005,
|
||||
a34011,
|
||||
a34013,
|
||||
a34017,
|
||||
a34038,
|
||||
a34039,
|
||||
a34040,
|
||||
a99010,
|
||||
a99049,
|
||||
//a99051,
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
using Swashbuckle.AspNetCore.SwaggerUI;
|
||||
using System.ComponentModel;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace langguanApi.Model
|
||||
{
|
||||
public class HJ212 : BaseModel
|
||||
{
|
||||
/// <summary>
|
||||
/// 设备ID
|
||||
/// </summary>
|
||||
public string deviceMN { get; set; }
|
||||
/// <summary>
|
||||
/// PM2.5浓度
|
||||
/// </summary>
|
||||
public double a34004 { get; set; }
|
||||
/// <summary>
|
||||
/// PM10浓度
|
||||
/// </summary>
|
||||
public double a34002 { get; set; }
|
||||
/// <summary>
|
||||
/// TSP浓度
|
||||
/// </summary>
|
||||
public double a34001 { get; set; }
|
||||
/// <summary>
|
||||
/// 温度
|
||||
/// </summary>
|
||||
public double a01001 { get; set; }
|
||||
/// <summary>
|
||||
/// 湿度
|
||||
/// </summary>
|
||||
public double a01002 { get; set; }
|
||||
/// <summary>
|
||||
/// 大气压
|
||||
/// </summary>
|
||||
public double a01006 { get; set; }
|
||||
/// <summary>
|
||||
/// 风速
|
||||
/// </summary>
|
||||
public double a01007 { get; set; }
|
||||
/// <summary>
|
||||
/// 风向
|
||||
/// </summary>
|
||||
public double a01008 { get; set; }
|
||||
public double lat { get; set; }
|
||||
public double lng { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 检测仪器数据标记
|
||||
/// </summary>
|
||||
public enum InstrumentationDataFlag
|
||||
{
|
||||
/// <summary>
|
||||
/// 正常(有效)
|
||||
/// <para>在线监控(监测)仪器仪表工作正常</para>
|
||||
/// </summary>
|
||||
N,
|
||||
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// <para>在线监控(监测)仪器仪表停运</para>
|
||||
/// </summary>
|
||||
F,
|
||||
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// <para>在线监控(监测)仪器仪表处于维护期间产生的数据 </para>
|
||||
/// </summary>
|
||||
M,
|
||||
|
||||
/// <summary>
|
||||
/// 有效
|
||||
/// <para>手工输入的设定值</para>
|
||||
/// </summary>
|
||||
S,
|
||||
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// <para>在线监控(监测)仪器仪表故障</para>
|
||||
/// </summary>
|
||||
D,
|
||||
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// <para>在线监控(监测)仪器仪表处于校准状态</para>
|
||||
/// </summary>
|
||||
C,
|
||||
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// <para>在线监控(监测)仪器仪表采样数值超过测量上限</para>
|
||||
/// </summary>
|
||||
T,
|
||||
|
||||
/// <summary>
|
||||
/// 无效
|
||||
/// <para>在线监控(监测)仪器仪表与数采仪通讯异常</para>
|
||||
/// </summary>
|
||||
B,
|
||||
|
||||
/// <summary>
|
||||
/// 无效(有效数据不足)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 按照5分钟、1小时均值计算要求,所获取的有效数据个数不足
|
||||
/// </remarks>
|
||||
H
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
using System.Text;
|
||||
|
||||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 通讯包
|
||||
/// </summary>
|
||||
public class NetPackage
|
||||
{
|
||||
/// <summary>
|
||||
/// 默认头
|
||||
/// </summary>
|
||||
public const string FixedHead = "##";
|
||||
/// <summary>
|
||||
/// 默认尾
|
||||
/// </summary>
|
||||
public const string FixedTail = "\r\n";
|
||||
|
||||
/// <summary>
|
||||
/// 包头
|
||||
/// </summary>
|
||||
public string Head { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据段长度
|
||||
/// </summary>
|
||||
public int DataSegmentLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据段
|
||||
/// </summary>
|
||||
public DataSegment DataSegment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CRC校验码
|
||||
/// </summary>
|
||||
public string CrcCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 包尾
|
||||
/// </summary>
|
||||
public string Tail { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CRC16校验
|
||||
/// </summary>
|
||||
/// <param name="arg">需要校验的字符串</param>
|
||||
/// <returns>CRC16 校验码</returns>
|
||||
private static string CRC16(string arg)
|
||||
{
|
||||
char[] puchMsg = arg.ToCharArray();
|
||||
uint i, j, crc_reg, check;
|
||||
crc_reg = 0xFFFF;
|
||||
for (i = 0; i < puchMsg.Length; i++)
|
||||
{
|
||||
crc_reg = (crc_reg >> 8) ^ puchMsg[i];
|
||||
for (j = 0; j < 8; j++)
|
||||
{
|
||||
check = crc_reg & 0x0001;
|
||||
crc_reg >>= 1;
|
||||
if (check == 0x0001)
|
||||
{
|
||||
crc_reg ^= 0xA001;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc_reg.ToString("X2").PadLeft(4, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析
|
||||
/// </summary>
|
||||
/// <param name="line"></param>
|
||||
/// <param name="unpackCacheFunc"></param>
|
||||
/// <returns></returns>
|
||||
public static NetPackage Parse(string line, Func<StringBuilder> unpackCacheFunc = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
NetPackage netPackage = new NetPackage();
|
||||
netPackage.Head = line.Substring(0, 2);
|
||||
netPackage.DataSegmentLength = int.Parse(line.Substring(2, 4));
|
||||
|
||||
string dataSegment = line.Substring(6, netPackage.DataSegmentLength);
|
||||
|
||||
string crcCode = line.Substring(6 + netPackage.DataSegmentLength, 4);
|
||||
string calcCrcCode = CRC16(dataSegment);
|
||||
if (crcCode != calcCrcCode)
|
||||
{
|
||||
throw new Exception("CRC校验失败 " + line);
|
||||
}
|
||||
|
||||
netPackage.DataSegment = DataSegment.Parse(dataSegment, unpackCacheFunc);
|
||||
netPackage.CrcCode = crcCode;
|
||||
netPackage.Tail = line.Substring(10 + netPackage.DataSegmentLength);
|
||||
|
||||
return netPackage;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Error in NetPackage.Parse", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string Serialize()
|
||||
{
|
||||
string dataSegment = DataSegment.Serialize();
|
||||
DataSegmentLength = dataSegment.Length;
|
||||
CrcCode = CRC16(dataSegment);
|
||||
|
||||
return $"{Head}{DataSegmentLength.ToString().PadLeft(4, '0')}{dataSegment}{CrcCode}{Tail}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 拆分包及应答标志
|
||||
/// </summary>
|
||||
public class PackageFlag
|
||||
{
|
||||
public byte V5 { get; set; }
|
||||
public byte V4 { get; set; }
|
||||
public byte V3 { get; set; }
|
||||
public byte V2 { get; set; }
|
||||
public byte V1 { get; set; }
|
||||
public byte V0 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 命令是否应答:1-应答,0-不应答
|
||||
/// </summary>
|
||||
public byte A { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否有数据包序号:1 - 数据包中包含包号和总包数两部分,0 - 数据包中不包含包号和总包数两部分
|
||||
/// </summary>
|
||||
public byte D { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标准版本号
|
||||
/// <para>000000 表示标准 HJ/T212-2005</para>
|
||||
/// <para>000001 表示本次标准修订版本号</para>
|
||||
/// </summary>
|
||||
public string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"{V5}{V4}{V3}{V2}{V1}{V0}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public static PackageFlag Parse(string data)
|
||||
{
|
||||
byte flag = byte.Parse(data);
|
||||
return new PackageFlag()
|
||||
{
|
||||
|
||||
V5 = GetBit(flag, 7),
|
||||
V4 = GetBit(flag, 6),
|
||||
V3 = GetBit(flag, 5),
|
||||
V2 = GetBit(flag, 4),
|
||||
V1 = GetBit(flag, 3),
|
||||
V0 = GetBit(flag, 2),
|
||||
D = GetBit(flag, 1),
|
||||
A = GetBit(flag, 0)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 序列化
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string Serialize()
|
||||
{
|
||||
return Convert.ToInt32($"{V5}{V4}{V3}{V2}{V1}{V0}{D}{A}", 2).ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取取第index位
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// index从0开始
|
||||
/// </remarks>
|
||||
/// <param name="b"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
private static byte GetBit(byte b, int index)
|
||||
{
|
||||
// (byte)((from & (0xFF << (index * 8))) >> (index * 8))
|
||||
return ((b & (1 << index)) > 0) ? (byte)1 : (byte)0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将第index位设为1
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// index从0开始
|
||||
/// </remarks>
|
||||
/// <param name="b"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
private static byte SetBit(byte b, int index) { return (byte)(b | (1 << index)); }
|
||||
|
||||
/// <summary>
|
||||
/// 将第index位设为0
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// index从0开始
|
||||
/// </remarks>
|
||||
/// <param name="b"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
private static byte ClearBit(byte b, int index) { return (byte)(b & (byte.MaxValue - (1 << index))); }
|
||||
|
||||
/// <summary>
|
||||
/// 将第index位取反
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// index从0开始
|
||||
/// </remarks>
|
||||
/// <param name="b"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <returns></returns>
|
||||
private static byte ReverseBit(byte b, int index) { return (byte)(b ^ (byte)(1 << index)); }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 污染物信息
|
||||
/// </summary>
|
||||
public class PollutantInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 约定的无效值
|
||||
/// </summary>
|
||||
public const decimal InvaildValue = -9999;
|
||||
|
||||
/// <summary>
|
||||
/// 污染物因子编码
|
||||
/// </summary>
|
||||
public FactorCode FactorCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 污染物实时采样数据
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 默认值为约定的无效值 <see cref="InvaildValue"/>
|
||||
/// </remarks>
|
||||
public decimal Rtd { get; set; } = InvaildValue;
|
||||
|
||||
/// <summary>
|
||||
/// 污染物指定时问内平均值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 默认值为约定的无效值 <see cref="InvaildValue"/>
|
||||
/// </remarks>
|
||||
public decimal Avg { get; set; } = InvaildValue;
|
||||
|
||||
/// <summary>
|
||||
/// 污染物指定时问内最大值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 默认值为约定的无效值 <see cref="InvaildValue"/>
|
||||
/// </remarks>
|
||||
public decimal Max { get; set; } = InvaildValue;
|
||||
|
||||
/// <summary>
|
||||
/// 污染物指定时问内最小值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 默认值为约定的无效值 <see cref="InvaildValue"/>
|
||||
/// </remarks>
|
||||
public decimal Min { get; set; } = InvaildValue;
|
||||
|
||||
/// <summary>
|
||||
/// 污染物指定时问内累计值
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 默认值为约定的无效值 <see cref="InvaildValue"/>
|
||||
/// </remarks>
|
||||
public decimal Cou { get; set; } = InvaildValue;
|
||||
|
||||
/// <summary>
|
||||
/// 检测仪器数据标记
|
||||
/// </summary>
|
||||
public InstrumentationDataFlag Flag { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
public class ReqPaing
|
||||
{
|
||||
public int pageSize { get; set; } = 10;
|
||||
public int current { get; set; } = 1;
|
||||
}
|
||||
public class reqpage : ReqPaing
|
||||
{
|
||||
public string key { get; set;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// 回应代码集
|
||||
/// </summary>
|
||||
public enum ResponseCode
|
||||
{
|
||||
/// <summary>
|
||||
/// 执行成功
|
||||
/// </summary>
|
||||
ExecSucceeded = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 执行失败,但不知道原因
|
||||
/// </summary>
|
||||
ExecutionFailed_DoNotKnowReason = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 执行失败,命令请求条件错误
|
||||
/// </summary>
|
||||
ExecutionFailed_InvalidCommand = 3,
|
||||
|
||||
/// <summary>
|
||||
/// 通讯超时
|
||||
/// </summary>
|
||||
CommunicationTimeout = 4,
|
||||
|
||||
/// <summary>
|
||||
/// 系统繁忙不能执行
|
||||
/// </summary>
|
||||
SystemBusy = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 系统时间异常
|
||||
/// </summary>
|
||||
InvalidSystemTime = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 没有数据
|
||||
/// </summary>
|
||||
NoneData = 100,
|
||||
|
||||
/// <summary>
|
||||
/// 心跳包
|
||||
/// </summary>
|
||||
HeartbeatPackage = 300
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
namespace langguanApi.Model
|
||||
{
|
||||
public class columnView
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string hour { get; set; }
|
||||
/// <summary>
|
||||
/// a34004=PM2.5浓度,a34002=PM10,a34001=tsp浓度
|
||||
/// </summary>
|
||||
public string type { get; set; }
|
||||
public double value { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
using langguanApi.Common.Redis;
|
||||
using langguanApi.Extensions;
|
||||
using langguanApi.Extensions.AutoDI;
|
||||
using langguanApi.Middleware;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using System.Text.Json;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
|
||||
// Add services to the container.
|
||||
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
options.Filters.Add<CustomerExceptionFilter>();
|
||||
}).AddNewtonsoftJson(option =>
|
||||
{
|
||||
option.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();
|
||||
option.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
}).AddJsonOptions(option =>
|
||||
{
|
||||
option.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
||||
});
|
||||
//swagger
|
||||
builder.Services.AddSwaggerGen(
|
||||
options =>
|
||||
{
|
||||
options.SwaggerDoc("v1", new OpenApiInfo()
|
||||
{
|
||||
Title = "Title",
|
||||
Version = "v1",
|
||||
Description = "Description",
|
||||
});
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "langguanApi.xml");
|
||||
options.IncludeXmlComments(path, true);
|
||||
options.OrderActionsBy(_ => _.RelativePath);
|
||||
});
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
|
||||
//redis
|
||||
var redisoptions = builder.Configuration.GetSection("Redis").Get<RedisOptions>();
|
||||
if (redisoptions != null)
|
||||
{
|
||||
builder.Services.AddRedis(options =>
|
||||
{
|
||||
options.Port = redisoptions.Port;
|
||||
options.Server = redisoptions.Server;
|
||||
options.Index = redisoptions.Index;
|
||||
options.Password = redisoptions.Password;
|
||||
options.Key = redisoptions.Key;
|
||||
});
|
||||
}
|
||||
//×Ô¶¯×¢Èë
|
||||
builder.Services.ServicesAutoInjectionExtension();
|
||||
builder.Services.AddSocketService();
|
||||
//cross domain
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy", builder =>
|
||||
{
|
||||
builder.AllowAnyOrigin();
|
||||
builder.AllowAnyMethod();
|
||||
builder.AllowAnyHeader();
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
ServiceLocator.Instance = app.Services;
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
app.UseCors("CorsPolicy");
|
||||
//app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
/// <summary>
|
||||
/// ÔÝ´æ·þÎñ
|
||||
/// </summary>
|
||||
public static class ServiceLocator
|
||||
{
|
||||
public static IServiceProvider Instance { get; set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"profiles": {
|
||||
"langguanApi": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5254"
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Docker": {
|
||||
"commandName": "Docker",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_URLS": "http://+:80"
|
||||
},
|
||||
"publishAllPorts": true
|
||||
}
|
||||
},
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:9471",
|
||||
"sslPort": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using langguanApi.Extensions.AutoDI;
|
||||
using langguanApi.Model;
|
||||
using langguanApi.Model.Dto;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
[ServiceInjection(InjectionType.Transient)]
|
||||
public class AlertService : BaseService<Alert>
|
||||
{
|
||||
public AlertService(IConfiguration config) : base(config, nameof(Device))
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 新加
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> Add(Alert input)
|
||||
{
|
||||
if (input != null)
|
||||
{
|
||||
await base.CreateAsync(input);
|
||||
return new ApiResult { code = 0, msg = "" };
|
||||
}
|
||||
return new ApiResult { code = -1, msg = "" }; ;
|
||||
}
|
||||
/// <summary>
|
||||
/// 分页取数据
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<object> GetPage(reqpage input)
|
||||
{
|
||||
Expression<Func<Alert, bool>> exp = filter => filter.DeviceMn.Contains(input.key) && filter.IsDelete == false;
|
||||
return await base.GetPager(new ReqPaing()
|
||||
{
|
||||
pageSize = input.pageSize,
|
||||
current = input.current
|
||||
}, exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
using langguanApi.Model;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using MongoDB.Driver;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
public class BaseService<T> where T : BaseModel
|
||||
{
|
||||
private readonly IMongoCollection<T> _collection; //数据表操作对象
|
||||
/// <summary>
|
||||
/// 构造
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
/// <param name="tableName"></param>
|
||||
public BaseService(IConfiguration config, string tableName)
|
||||
{
|
||||
|
||||
var client = new MongoClient(config.GetSection("ConnectionStrings:MongoDBConn").Value); //获取链接字符串
|
||||
var database = client.GetDatabase(config.GetSection("ConnectionStrings:DBName").Value);
|
||||
_collection = database.GetCollection<T>(tableName);
|
||||
if (_collection == null)
|
||||
{
|
||||
database.CreateCollection(tableName);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取所有
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<T> Get()
|
||||
{
|
||||
return _collection.Find(T => true).ToList();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取单个
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public T Get(string id)
|
||||
{
|
||||
return _collection.Find<T>(T => T.Id == id).FirstOrDefault();
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建
|
||||
/// </summary>
|
||||
/// <param name="T"></param>
|
||||
/// <returns></returns>
|
||||
public T Create(T T)
|
||||
{
|
||||
_collection.InsertOne(T);
|
||||
return T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="TIn"></param>
|
||||
public void Update(string id, T TIn)
|
||||
{
|
||||
_collection.ReplaceOne(T => T.Id == id, TIn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除
|
||||
/// </summary>
|
||||
/// <param name="TIn"></param>
|
||||
public void Remove(T TIn)
|
||||
{
|
||||
_collection.DeleteOne(T => T.Id == TIn.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据id删除
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
public void Remove(string id)
|
||||
{
|
||||
_collection.DeleteOne(T => T.Id == id);
|
||||
}
|
||||
#region 异步操作
|
||||
/// <summary>
|
||||
/// 取列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<T>> GetAsync()
|
||||
{
|
||||
return await _collection.Find(T => true).ToListAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 取单条
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<T> GetAsync(string id)
|
||||
{
|
||||
return await _collection.Find<T>(T => T.Id == id).FirstOrDefaultAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 新增
|
||||
/// </summary>
|
||||
/// <param name="T"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<T> CreateAsync(T T)
|
||||
{
|
||||
await _collection.InsertOneAsync(T);
|
||||
return T;
|
||||
}
|
||||
/// <summary>
|
||||
/// 新增
|
||||
/// </summary>
|
||||
/// <param name="T"></param>
|
||||
/// <returns></returns>
|
||||
public async Task CreateManyAsync(IEnumerable<T> T)
|
||||
{
|
||||
await _collection.InsertManyAsync(T);
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="TIn"></param>
|
||||
/// <returns></returns>
|
||||
public async Task UpdateAsync(string id, T TIn)
|
||||
{
|
||||
await _collection.ReplaceOneAsync(T => T.Id == id, TIn);
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public async Task RemoveAsync(string id)
|
||||
{
|
||||
await _collection.DeleteOneAsync(T => T.Id == id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
/// <summary>
|
||||
/// 表达式取数据
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
public Task<IQueryable<T>> GetListWithExp(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
// var temp = _collection.AsQueryable<T>().Where(expression).ToList();
|
||||
return Task.FromResult(_collection.AsQueryable<T>().Where(expression));
|
||||
}
|
||||
/// <summary>
|
||||
/// filter查找
|
||||
/// </summary>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<T>> FindListByFilter(Expression<Func<T, bool>> filter)
|
||||
{
|
||||
FilterDefinition<T> filters = Builders<T>.Filter.Where(filter);
|
||||
return await _collection.Find(filters).ToListAsync();
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// filterdefinition
|
||||
/// </summary>
|
||||
/// <param name="filter"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<T>> FindListyFilter(FilterDefinition<T> filter)
|
||||
{
|
||||
return await _collection.Find(filter).ToListAsync();
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> Exist(Expression<Func<T, bool>> expression)
|
||||
{
|
||||
var result = _collection.AsQueryable().Where(expression).Any();
|
||||
return Task.FromResult(result);
|
||||
}
|
||||
/// <summary>
|
||||
/// 分页取数据
|
||||
/// </summary>
|
||||
/// <param name="req"></param>
|
||||
/// <param name="exp"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> GetPager(ReqPaing req, Expression<Func<T, bool>> exp = null)
|
||||
{
|
||||
req.pageSize = req.pageSize == 0 ? 10 : req.pageSize;
|
||||
var query = await GetListWithExp(exp);
|
||||
var total = query.Count();
|
||||
var items = query.OrderByDescending(s => s.CreateDateTime)
|
||||
.Skip(req.pageSize * (req.current - 1)).Take(req.pageSize).ToList();
|
||||
return new ApiResult()
|
||||
{
|
||||
code = 0,
|
||||
data = new { total, items }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
using langguanApi.Extensions.AutoDI;
|
||||
using langguanApi.Model;
|
||||
using langguanApi.Model.Dto;
|
||||
using Mapster;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
[ServiceInjection(InjectionType.Scoped)]
|
||||
public class DeviceService : BaseService<Device>
|
||||
{
|
||||
public DeviceService(IConfiguration config) : base(config, nameof(Device))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新加
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> Add(DeviceDto input)
|
||||
{
|
||||
if (await Exist(input))
|
||||
{
|
||||
return new ApiResult { code = 1, msg = $"已经存在名称为:{input.Name}" };
|
||||
}
|
||||
var entity = input.Adapt<Device>();
|
||||
if (entity != null)
|
||||
{
|
||||
await base.CreateAsync(entity);
|
||||
return new ApiResult { code = 0, msg = "" };
|
||||
}
|
||||
return new ApiResult { code = -1, msg = "" }; ;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否存在
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> Exist(DeviceDto input)
|
||||
{
|
||||
var entity = input.Adapt<Device>();
|
||||
Expression<Func<Device, bool>> exp = filter => filter.deviceMN == entity.deviceMN;
|
||||
return await base.Exist(exp);
|
||||
}
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> update(DeviceDto input)
|
||||
{
|
||||
var entity = input.Adapt<Device>();
|
||||
await base.UpdateAsync(entity.Id, entity);
|
||||
return new ApiResult { code = 0, msg = "" };
|
||||
}
|
||||
/// <summary>
|
||||
/// remove
|
||||
/// </summary>
|
||||
/// <param name="ids"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> remove(IEnumerable<string> ids)
|
||||
{
|
||||
if (ids.Any())
|
||||
{
|
||||
foreach (var item in ids)
|
||||
{
|
||||
var entity = await base.GetAsync(item);
|
||||
entity.IsDelete = true;
|
||||
await base.UpdateAsync(entity.Id, entity);
|
||||
}
|
||||
return new ApiResult { code = 0, msg = "" };
|
||||
}
|
||||
return new ApiResult { code = -1, msg = "" };
|
||||
}
|
||||
// 通过devicemn获取设备信息
|
||||
public async Task<Device> GetByDeviceMN(string deviceMN)
|
||||
{
|
||||
Expression<Func<Device, bool>> exp = filter => filter.deviceMN == deviceMN && filter.IsDelete == false;
|
||||
return (await base.GetListWithExp(exp)).FirstOrDefault();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 分页取数据
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<object> GetPage(reqpage input)
|
||||
{
|
||||
Expression<Func<Device, bool>> exp = filter => filter.Name.Contains(input.key) && filter.IsDelete == false;
|
||||
return await base.GetPager(new ReqPaing()
|
||||
{
|
||||
pageSize = input.pageSize,
|
||||
current = input.current
|
||||
}, exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
using IceCoffee.FastSocket.Tcp;
|
||||
using langguanApi.Model;
|
||||
using System.Net;
|
||||
|
||||
namespace langguanApi.Service.HJ212
|
||||
{
|
||||
public class NetServer : TcpServer
|
||||
{
|
||||
/// <summary>
|
||||
/// 收到数据事件
|
||||
/// </summary>
|
||||
public event Action<NetSession, NetPackage, string> ReceivedData;
|
||||
/// <summary>
|
||||
/// 发送数据事件
|
||||
/// </summary>
|
||||
public event Action<NetSession, NetPackage, string> SendData;
|
||||
|
||||
public NetServer(IPAddress address, int port, TcpServerOptions options = null)
|
||||
: base(address, port, options ?? new TcpServerOptions() { KeepAlive = true })
|
||||
{
|
||||
}
|
||||
public NetServer(string address, int port, TcpServerOptions options = null)
|
||||
: base(address, port, options ?? new TcpServerOptions() { KeepAlive = true })
|
||||
{
|
||||
}
|
||||
public NetServer(IPEndPoint endPoint, TcpServerOptions options = null)
|
||||
: base(endPoint, options ?? new TcpServerOptions() { KeepAlive = true })
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override TcpSession CreateSession()
|
||||
{
|
||||
return new NetSession(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 引发收到数据事件
|
||||
/// </summary>
|
||||
internal void RaiseReceivedData(NetSession netSession, NetPackage netPackage, string rawText)
|
||||
{
|
||||
ReceivedData?.Invoke(netSession, netPackage, rawText);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 引发发送数据事件
|
||||
/// </summary>
|
||||
/// <param name="netSession"></param>
|
||||
/// <param name="netPackage"></param>
|
||||
/// <param name="rawText"></param>
|
||||
internal void RaiseSendData(NetSession netSession, NetPackage netPackage, string rawText)
|
||||
{
|
||||
SendData?.Invoke(netSession, netPackage, rawText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
using IceCoffee.FastSocket.Tcp;
|
||||
using langguanApi.Model;
|
||||
using System.Text;
|
||||
|
||||
namespace langguanApi.Service.HJ212
|
||||
{
|
||||
public class NetSession : TcpSession
|
||||
{
|
||||
private StringBuilder _unpackCache;
|
||||
|
||||
public NetSession(TcpServer server) : base(server)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnClosed()
|
||||
{
|
||||
base.OnClosed();
|
||||
_unpackCache?.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取分包缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private StringBuilder GetUnpackCache()
|
||||
{
|
||||
return _unpackCache ??= new StringBuilder();
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override void OnReceived()
|
||||
{
|
||||
if (ReadBuffer.IndexOf(35) != 0L)// '#'
|
||||
{
|
||||
return;
|
||||
// throw new Exception("异常TCP连接 IP: " + RemoteIPEndPoint);
|
||||
}
|
||||
|
||||
string rawText = null;
|
||||
while (ReadBuffer.CanReadLine)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] data = ReadBuffer.ReadLine();
|
||||
rawText = Encoding.UTF8.GetString(data);
|
||||
NetPackage netPackage = NetPackage.Parse(rawText, GetUnpackCache);
|
||||
((NetServer)Server).RaiseReceivedData(this, netPackage, rawText);
|
||||
|
||||
if (netPackage.DataSegment.PackageFlag != null && netPackage.DataSegment.PackageFlag.A == 1)
|
||||
{
|
||||
Response(netPackage);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"error :OnReceived:{ex.Message},data:{ex.Data}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应答
|
||||
/// </summary>
|
||||
private void Response(NetPackage netPackage)
|
||||
{
|
||||
try
|
||||
{
|
||||
netPackage.DataSegment.ST = DataSegment.ResponseST;
|
||||
netPackage.DataSegment.CN = CommandNumber.DataResponse;
|
||||
netPackage.DataSegment.PackageFlag.A = 0;
|
||||
netPackage.DataSegment.PackageFlag.D = 0;
|
||||
netPackage.DataSegment.CpCommand.ExeRtn = ResponseCode.ExecSucceeded;
|
||||
|
||||
string rawText = netPackage.Serialize();
|
||||
byte[] data = Encoding.UTF8.GetBytes(rawText);
|
||||
SendAsync(data);
|
||||
|
||||
((NetServer)Server).RaiseSendData(this, netPackage, rawText);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception("Error in NetSession", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using IceCoffee.FastSocket.Tcp;
|
||||
using langguanApi.Model.Dto;
|
||||
using Newtonsoft.Json;
|
||||
using langguanApi.Model;
|
||||
using langguanApi.Service.HJ212;
|
||||
using langguanApi.Extensions.AutoDI;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
|
||||
public class HJ212SocketServer
|
||||
{
|
||||
private Hj212Service _hj212Service;
|
||||
public HJ212SocketServer(Hj212Service hj212Service)
|
||||
{
|
||||
_hj212Service = hj212Service;
|
||||
}
|
||||
/// <summary>
|
||||
/// 缓冲器
|
||||
/// </summary>
|
||||
private byte[] result = new byte[1024];
|
||||
/// <summary>
|
||||
/// 最大连接数
|
||||
/// </summary>
|
||||
private int maxClientCount;
|
||||
/// <summary>
|
||||
/// 服务IP地址
|
||||
/// </summary>
|
||||
private string ip;
|
||||
/// <summary>
|
||||
/// 服务端口号
|
||||
/// </summary>
|
||||
private int port => 5001;
|
||||
// 编码
|
||||
// private string code;
|
||||
/// <summary>
|
||||
/// 客户端列表
|
||||
/// </summary>
|
||||
private List<Socket> ClientSockets;
|
||||
/// <summary>
|
||||
/// IP终端
|
||||
/// </summary>
|
||||
private IPEndPoint ipEndPoint;
|
||||
/// <summary>
|
||||
/// 服务端Socket
|
||||
/// </summary>
|
||||
private Socket ServerSocket;
|
||||
private static NetServer server;
|
||||
private static IceCoffee.FastSocket.Tcp.TcpClient client;
|
||||
/// <summary>
|
||||
/// 启动服务
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task Start()
|
||||
{
|
||||
ip = IPAddress.Any.ToString();
|
||||
server = new NetServer(ip, port);
|
||||
server.Started += OnNetServer_Started;
|
||||
server.ExceptionCaught += OnNetServer_ExceptionCaught;
|
||||
server.SessionStarted += OnNetServer_SessionStarted;
|
||||
server.SessionClosed += OnNetServer_SessionClosed;
|
||||
server.ReceivedData += OnNetServer_ReceivedData;
|
||||
server.SendData += OnNetServer_SendData;
|
||||
server.Start();
|
||||
}
|
||||
private void OnNetServer_Started()
|
||||
{
|
||||
Console.WriteLine($"开始监听: {ip}:{port}");
|
||||
}
|
||||
|
||||
private void OnNetServer_SendData(NetSession session, NetPackage netPackage, string rawText)
|
||||
{
|
||||
Console.WriteLine($"发送给: {session.RemoteIPEndPoint}: {rawText}");
|
||||
}
|
||||
|
||||
private void OnNetServer_SessionClosed(TcpSession session)
|
||||
{
|
||||
Console.WriteLine("会话关闭: " + session.RemoteIPEndPoint + ", 当前会话总数: " + server.SessionCount);
|
||||
}
|
||||
|
||||
private static void OnNetServer_SessionStarted(TcpSession session)
|
||||
{
|
||||
Console.WriteLine("会话开始: " + session.RemoteIPEndPoint + ", 当前会话总数: " + server.SessionCount);
|
||||
}
|
||||
|
||||
private async void OnNetServer_ReceivedData(TcpSession session, NetPackage netPackage, string rawText)
|
||||
{
|
||||
Console.WriteLine("收到自: " + session.RemoteIPEndPoint + ": " + rawText);
|
||||
HJ212_2017 hj = new HJ212_2017();
|
||||
if (hj.DecodeData(rawText))
|
||||
{
|
||||
var body = JsonConvert.SerializeObject(hj.CP);
|
||||
var entity = JsonConvert.DeserializeObject<Model.HJ212>(body);
|
||||
entity.deviceMN = hj.DATA_HEAD["MN"];
|
||||
//校验通过,开始入库
|
||||
await _hj212Service.Add(entity, session.RemoteIPEndPoint.ToString());
|
||||
}
|
||||
}
|
||||
private void OnNetServer_ExceptionCaught(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Error in NetServer" + ex);
|
||||
}
|
||||
byte[] CallCRC(byte[] data)
|
||||
{
|
||||
string ccc = Convert.ToString(getCrc(data), 16).PadLeft(4, '0');
|
||||
return Encoding.ASCII.GetBytes(ccc.ToUpper());
|
||||
}
|
||||
private int getCrc(byte[] data)
|
||||
{
|
||||
int high;
|
||||
int flag;
|
||||
|
||||
// 16位寄存器,所有数位均为1
|
||||
int wcrc = 0xffff;
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
// 16 位寄存器的高位字节
|
||||
high = wcrc >> 8;
|
||||
// 取被校验串的一个字节与 16 位寄存器的高位字节进行“异或”运算
|
||||
wcrc = high ^ data[i];
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
flag = wcrc & 0x0001;
|
||||
// 把这个 16 寄存器向右移一位
|
||||
wcrc = wcrc >> 1;
|
||||
// 若向右(标记位)移出的数位是 1,则生成多项式 1010 0000 0000 0001 和这个寄存器进行“异或”运算
|
||||
if (flag == 1)
|
||||
wcrc ^= 0xa001;
|
||||
}
|
||||
}
|
||||
|
||||
return wcrc;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
using langguanApi.Extensions.AutoDI;
|
||||
using langguanApi.Model;
|
||||
using langguanApi.Model.Dto;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
[ServiceInjection(InjectionType.Transient)]
|
||||
public class Hj212Service : BaseService<Model.HJ212>
|
||||
{
|
||||
private DeviceService _deviceSerive;
|
||||
public Hj212Service(IConfiguration config, DeviceService deviceSerive) : base(config, nameof(Model.HJ212))
|
||||
{
|
||||
_deviceSerive = deviceSerive;
|
||||
}
|
||||
/// <summary>
|
||||
/// 新加数据
|
||||
/// </summary>
|
||||
/// <param name="hJ212"></param>
|
||||
/// <param name="deviceIp"></param>
|
||||
/// <returns></returns>
|
||||
public async Task Add(Model.HJ212 hJ212, string deviceIp)
|
||||
{
|
||||
//先判断当前设备是否存在
|
||||
await _deviceSerive.Add(new DeviceDto()
|
||||
{
|
||||
deviceMN = hJ212.deviceMN,
|
||||
Ip = deviceIp,
|
||||
lat = hJ212.lat,
|
||||
lng = hJ212.lng,
|
||||
state = 1
|
||||
});
|
||||
await base.CreateAsync(hJ212);
|
||||
}
|
||||
/// <summary>
|
||||
/// 最近10个小时的数据
|
||||
/// </summary>
|
||||
/// <param name="hours"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<Model.HJ212>> GetViewTop(int hours = -10)
|
||||
{
|
||||
var date = DateTime.Now.AddHours(-8).AddHours(hours);
|
||||
Expression<Func<Model.HJ212, bool>> exp = filter => filter.CreateDateTime >= date;
|
||||
var result = (await base.GetListWithExp(exp)).ToList();
|
||||
|
||||
return result;
|
||||
}
|
||||
/// <summary>
|
||||
/// 按设备号查询数据
|
||||
/// </summary>
|
||||
/// <param name="deviceMn"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<object>GetViewByDeviceMn(string deviceMn)
|
||||
{
|
||||
Expression<Func<Model.HJ212, bool>> exp = filter => filter.deviceMN == deviceMn;
|
||||
var result = (await base.GetListWithExp(exp)).OrderByDescending(s => s.CreateDateTime).Take(60).ToList();
|
||||
List<columnView> list = new List<columnView>();
|
||||
var temp = result.Select(s => new
|
||||
{
|
||||
s.a34001,
|
||||
s.a34002,
|
||||
s.a34004,
|
||||
hour = s.CreateDateTime.AddHours(8).ToString("yyyy-MM-dd HH:mm")
|
||||
}).ToList();
|
||||
|
||||
temp.GroupBy(g => new { g.hour }).ToList().ForEach(s =>
|
||||
{
|
||||
var v1 = temp.Where(m => m.hour == s.Key.hour).Sum(t => t.a34001);
|
||||
var v2 = temp.Where(m => m.hour == s.Key.hour).Sum(t => t.a34002);
|
||||
var v3 = temp.Where(m => m.hour == s.Key.hour).Sum(t => t.a34004);
|
||||
list.Add(new columnView() { hour = s.Key.hour, type = "a34001", value = v1 });
|
||||
list.Add(new columnView() { hour = s.Key.hour, type = "a34002", value = Math.Round(v2, 2) });
|
||||
list.Add(new columnView() { hour = s.Key.hour, type = "a34004", value = Math.Round(v3, 2) });
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 实时的数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<columnView>> Realtime()
|
||||
{
|
||||
Expression<Func<Model.HJ212, bool>> exp = filter => true;
|
||||
var result = (await base.GetListWithExp(exp)).OrderByDescending(s => s.CreateDateTime)
|
||||
.Take(60).OrderBy(s => s.CreateDateTime).ToList();
|
||||
List<columnView> list = new List<columnView>();
|
||||
var temp = result.Select(s => new
|
||||
{
|
||||
s.a34001,
|
||||
s.a34002,
|
||||
s.a34004,
|
||||
hour = s.CreateDateTime.AddHours(8).ToString("yyyy-MM-dd HH:mm")
|
||||
}).ToList();
|
||||
|
||||
temp.GroupBy(g => new { g.hour }).ToList().ForEach(s =>
|
||||
{
|
||||
var v1 = temp.Where(m => m.hour == s.Key.hour).Sum(t => t.a34001);
|
||||
var v2 = temp.Where(m => m.hour == s.Key.hour).Sum(t => t.a34002);
|
||||
var v3 = temp.Where(m => m.hour == s.Key.hour).Sum(t => t.a34004);
|
||||
list.Add(new columnView() { hour = s.Key.hour, type = "a34001", value = v1 });
|
||||
list.Add(new columnView() { hour = s.Key.hour, type = "a34002", value = Math.Round(v2, 2) });
|
||||
list.Add(new columnView() { hour = s.Key.hour, type = "a34004", value = Math.Round(v3, 2) });
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
using langguanApi.Common.Redis;
|
||||
using langguanApi.Common;
|
||||
using langguanApi.Extensions.AutoDI;
|
||||
using langguanApi.Model;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
/// <summary>
|
||||
/// HomeService
|
||||
/// </summary>
|
||||
[ServiceInjection(InjectionType.Scoped)]
|
||||
public class HomeService
|
||||
{
|
||||
private DeviceService _deviceService;
|
||||
private Hj212Service _hj212Service;
|
||||
private readonly IConfiguration _configuration;
|
||||
private CacheManager _cacheManager;
|
||||
private readonly WeatherService _weatherService;
|
||||
/// <summary>
|
||||
/// HomeService
|
||||
/// </summary>
|
||||
/// <param name="device"></param>
|
||||
/// <param name="hj212Service"></param>
|
||||
public HomeService(DeviceService device, Hj212Service hj212Service,
|
||||
IConfiguration configuration, CacheManager cacheManager, WeatherService weatherService)
|
||||
{
|
||||
_deviceService = device;
|
||||
_hj212Service = hj212Service;
|
||||
_configuration = configuration;
|
||||
_cacheManager = cacheManager;
|
||||
_weatherService = weatherService;
|
||||
}
|
||||
/// <summary>
|
||||
/// view
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<ApiResult> View()
|
||||
{
|
||||
var devices = await _deviceService.GetAsync();
|
||||
var ariQuality = "";
|
||||
Expression<Func<Model.HJ212, bool>> filter = exp => true;
|
||||
var Realtime = await _hj212Service.Realtime();
|
||||
var GetViewTop = await _hj212Service.GetViewTop();
|
||||
// 获取天气信息,缓存1小时,如果不存在,则调用WeatherService获取
|
||||
Func<Task<object>> getWeatherFunc = async () => await _weatherService.GetWeather();
|
||||
var weather = await _cacheManager.GetConvertVale(RedisKeylist.Weather, getWeatherFunc, 60 * 60);
|
||||
return new ApiResult
|
||||
{
|
||||
code = 0,
|
||||
data = new
|
||||
{
|
||||
home = new
|
||||
{
|
||||
center = new
|
||||
{
|
||||
lon = _configuration.GetValue<double>("Home:Center:Lon"),
|
||||
lat = _configuration.GetValue<double>("Home:Center:Lat"),
|
||||
},
|
||||
title = _configuration.GetValue<string>("Home:Title"),
|
||||
},
|
||||
devices,
|
||||
ariQuality,
|
||||
Realtime,
|
||||
GetViewTop
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
using langguanApi.Extensions.AutoDI;
|
||||
using System.Net.NetworkInformation;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// ping service
|
||||
/// </summary>
|
||||
public class PingService
|
||||
{
|
||||
|
||||
private DeviceService _deviceSerive;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="deviceSerive"></param>
|
||||
public PingService(DeviceService deviceSerive)
|
||||
{
|
||||
_deviceSerive = deviceSerive;
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public void CreatTask()
|
||||
{
|
||||
//5分钟执行一次
|
||||
|
||||
Timer myTimer = new Timer(new TimerCallback(Execute), null, 2000, 300000);
|
||||
// Timer myTimer = new Timer(new TimerCallback(Execute), "ping service", 2000, 10000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="b"></param>
|
||||
public async void Execute(object b)
|
||||
{
|
||||
var deviceList = await _deviceSerive.GetAsync();
|
||||
if (deviceList.Any())
|
||||
{
|
||||
foreach (var item in deviceList)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Ip))
|
||||
{
|
||||
var ip = item.Ip.Split(":")[0];
|
||||
var res = await PingIp(ip);
|
||||
item.state = res == true ? 1 : 0;
|
||||
await _deviceSerive.UpdateAsync(item.Id, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("{0} ping running.", (string)b);
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// ping
|
||||
/// </summary>
|
||||
/// <param name="ip"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> PingIp(string ip)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Ping 实例对象;
|
||||
Ping pingSender = new Ping();
|
||||
PingReply pingReply = await pingSender.SendPingAsync(ip);
|
||||
if (pingReply.Status == IPStatus.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace langguanApi.Service
|
||||
{
|
||||
public class WeatherService
|
||||
{
|
||||
private IHttpClientFactory _httpClientFactory;
|
||||
private IConfiguration _configuration;
|
||||
private ILogger<WeatherService> _logger;
|
||||
public WeatherService(IHttpClientFactory httpClientFactory,
|
||||
IConfiguration configuration, ILogger<WeatherService> logger)
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_configuration = configuration;
|
||||
_logger=logger;
|
||||
}
|
||||
/// <summary>
|
||||
/// 爬气象局的天气数据%
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<object> GetWeather()
|
||||
{
|
||||
try
|
||||
{
|
||||
var client = _httpClientFactory.CreateClient();
|
||||
var resp = await client.GetAsync(_configuration.GetSection("Weather").Value);
|
||||
if (resp.IsSuccessStatusCode)
|
||||
{
|
||||
var data = await resp.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<Root>(data);
|
||||
return new
|
||||
{
|
||||
location = result?.data.location.name,
|
||||
result?.data.now.precipitation,
|
||||
result?.data.now.temperature,
|
||||
result?.data.now.pressure,
|
||||
result?.data.now.humidity,
|
||||
result?.data.now.windDirection,
|
||||
result?.data.now.windDirectionDegree,
|
||||
result?.data.now.windSpeed,
|
||||
result?.data.now.windScale,
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public class Location
|
||||
{
|
||||
/// <summary>
|
||||
/// 54511
|
||||
/// </summary>
|
||||
public string id { get; set; }
|
||||
/// <summary>
|
||||
/// 北京
|
||||
/// </summary>
|
||||
public string name { get; set; }
|
||||
/// <summary>
|
||||
/// 中国, 北京, 北京
|
||||
/// </summary>
|
||||
public string path { get; set; }
|
||||
}
|
||||
|
||||
public class Now
|
||||
{
|
||||
/// <summary>
|
||||
/// Precipitation
|
||||
/// </summary>
|
||||
public double precipitation { get; set; }
|
||||
/// <summary>
|
||||
/// Temperature
|
||||
/// </summary>
|
||||
public double temperature { get; set; }
|
||||
/// <summary>
|
||||
/// Pressure
|
||||
/// </summary>
|
||||
public double pressure { get; set; }
|
||||
/// <summary>
|
||||
/// Humidity
|
||||
/// </summary>
|
||||
public double humidity { get; set; }
|
||||
/// <summary>
|
||||
/// 东北风
|
||||
/// </summary>
|
||||
public string windDirection { get; set; }
|
||||
/// <summary>
|
||||
/// WindDirectionDegree
|
||||
/// </summary>
|
||||
public double windDirectionDegree { get; set; }
|
||||
/// <summary>
|
||||
/// WindSpeed
|
||||
/// </summary>
|
||||
public double windSpeed { get; set; }
|
||||
/// <summary>
|
||||
/// 微风
|
||||
/// </summary>
|
||||
public string windScale { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Location
|
||||
/// </summary>
|
||||
public Location location { get; set; }
|
||||
/// <summary>
|
||||
/// Now
|
||||
/// </summary>
|
||||
public Now now { get; set; }
|
||||
/// <summary>
|
||||
/// Alarm
|
||||
/// </summary>
|
||||
public List<object> alarm { get; set; }
|
||||
/// <summary>
|
||||
/// 2024/01/15 10:05
|
||||
/// </summary>
|
||||
public DateTime lastUpdate { get; set; }
|
||||
}
|
||||
public class Root
|
||||
{
|
||||
/// <summary>
|
||||
/// success
|
||||
/// </summary>
|
||||
public string msg { get; set; }
|
||||
/// <summary>
|
||||
/// Code
|
||||
/// </summary>
|
||||
public int code { get; set; }
|
||||
/// <summary>
|
||||
/// Data
|
||||
/// </summary>
|
||||
public Data data { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"MongoDBConn": "mongodb://admin:adminn@101.43.201.20:8017",
|
||||
"DBName": "lg"
|
||||
},
|
||||
"Redis": {
|
||||
"Server": "101.43.201.20:6379,password=Aa123,abortConnect =false",
|
||||
"Key": "tdss",
|
||||
"Index": 5
|
||||
},
|
||||
"Weather": "https://weather.cma.cn/api/now/54511", //天气预报地址,中国气象
|
||||
"Home": {
|
||||
"Title": "鄂托克旗新航焦化有限公司",
|
||||
"Center": {
|
||||
"lat": 39.4716613,
|
||||
"lon": 107.1413332
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
</PropertyGroup>
|
||||
<!--生成时包含xml文件-->
|
||||
<PropertyGroup>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DocumentationFile>D:\work\langguanApi\langguanApi.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="IceCoffee.FastSocket" Version="1.0.3" />
|
||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.27" />
|
||||
<PackageReference Include="MongoDB.Bson" Version="2.23.1" />
|
||||
<PackageReference Include="MongoDB.Driver" Version="2.23.1" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.7.33" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Loading…
Reference in New Issue