diff --git a/Entity/Api/Req/QueryChargeOrderReq.cs b/Entity/Api/Req/QueryChargeOrderReq.cs index 87128f0..9e06379 100644 --- a/Entity/Api/Req/QueryChargeOrderReq.cs +++ b/Entity/Api/Req/QueryChargeOrderReq.cs @@ -12,11 +12,9 @@ namespace Entity.Api.Req - /// - /// Desc:订单编号 - /// Default: - /// Nullable:True - /// + /// + /// 订单编号 + /// public string? Sn {get;set;} /// diff --git a/Entity/Api/Resp/ChargeOrderResp.cs b/Entity/Api/Resp/ChargeOrderResp.cs index 473d33c..21ea145 100644 --- a/Entity/Api/Resp/ChargeOrderResp.cs +++ b/Entity/Api/Resp/ChargeOrderResp.cs @@ -203,6 +203,13 @@ namespace Entity.Api.Resp /// Nullable:True /// public DateTime? UpdatedTime {get;set;} + + + /// + /// 云平台订单号 + /// + + public string? CloudSn { get; set; } } } diff --git a/Entity/Constant/BaseEnumExtensions.cs b/Entity/Constant/BaseEnumExtensions.cs new file mode 100644 index 0000000..119004f --- /dev/null +++ b/Entity/Constant/BaseEnumExtensions.cs @@ -0,0 +1,30 @@ +using System.ComponentModel; +using System.Reflection; + +namespace Entity.Constant; + +public class BaseEnumExtensions +{ + //根据枚举获取注释 + public static string GetDescription(Enum value) + { + FieldInfo field = value.GetType().GetField(value.ToString()); + + DescriptionAttribute attribute = + Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; + + return attribute == null ? value.ToString() : attribute.Description; + } + + //根据code获取枚举 + public static T GetEnumByCode(int code) where T : Enum + { + return (T)Enum.ToObject(typeof(T), code); + } + + //根据code获取值 + public static string GetEnumDescriptionByCode(int code) where T : Enum + { + return GetDescription((T)Enum.ToObject(typeof(T), code)); + } +} \ No newline at end of file diff --git a/Entity/Constant/StationConstant.cs b/Entity/Constant/StationConstant.cs index 9443856..fa1ea4e 100644 --- a/Entity/Constant/StationConstant.cs +++ b/Entity/Constant/StationConstant.cs @@ -47,17 +47,7 @@ public class StationConstant } - public static class EnumExtensions - { - public static string GetDescription( Enum value) - { - FieldInfo field = value.GetType().GetField(value.ToString()); - - DescriptionAttribute attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; - - return attribute == null ? value.ToString() : attribute.Description; - } - } + } \ No newline at end of file diff --git a/Entity/DbModel/Station/BinInfo.cs b/Entity/DbModel/Station/BinInfo.cs index 73e1c19..ecae8a8 100644 --- a/Entity/DbModel/Station/BinInfo.cs +++ b/Entity/DbModel/Station/BinInfo.cs @@ -191,5 +191,18 @@ namespace Entity.DbModel.Station [SugarColumn(ColumnName="updated_time")] public DateTime? UpdatedTime {get;set;} + /// + /// 电池是否在为 + /// 0:不在位 1:在位 2:无效 + /// + + [SugarColumn(ColumnName="exists")] + public int? Exists { get; set; } + /// + /// 最后结束充电的时间 + /// + [SugarColumn(ColumnName="last_charge_finish_time")] + public DateTime? LastChargeFinishTime { get; set; } + } } diff --git a/Entity/DbModel/Station/SwapAmtOrder.cs b/Entity/DbModel/Station/SwapAmtOrder.cs index 6654330..f89c06e 100644 --- a/Entity/DbModel/Station/SwapAmtOrder.cs +++ b/Entity/DbModel/Station/SwapAmtOrder.cs @@ -150,6 +150,11 @@ namespace Entity.DbModel.Station /// [SugarColumn(ColumnName="updated_time")] public DateTime? UpdatedTime {get;set;} + + /// + /// 车牌 + /// + public string VehicleNo { get; set; } } } diff --git a/Entity/DbModel/Station/SwapOrder.cs b/Entity/DbModel/Station/SwapOrder.cs index 291f77a..2810476 100644 --- a/Entity/DbModel/Station/SwapOrder.cs +++ b/Entity/DbModel/Station/SwapOrder.cs @@ -11,137 +11,141 @@ namespace Entity.DbModel.Station [SugarTable("swap_order")] public partial class SwapOrder { - public SwapOrder(){ - - - } - /// - /// Desc:id - /// Default: - /// Nullable:False - /// - [SugarColumn(IsPrimaryKey=true,IsIdentity=true,ColumnName="id")] - public int Id {get;set;} - - /// - /// Desc:订单编号 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="sn")] - public string Sn {get;set;} - - /// - /// Desc:车牌号 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="vehicle_no")] - public string VehicleNo {get;set;} - - /// - /// Desc:车辆mac - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="vehicle_mac")] - public string VehicleMac {get;set;} - - /// - /// Desc:车辆vin码 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="vehicle_vin")] - public string VehicleVin {get;set;} - - /// - /// Desc:车辆进场时间 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="vehicle_enter_time")] - public DateTime? VehicleEnterTime {get;set;} - - /// - /// Desc:车辆离场时间 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="vehicle_leave_time")] - public DateTime? VehicleLeaveTime {get;set;} - - /// - /// Desc:换电开始时间 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="swap_begin_time")] - public DateTime? SwapBeginTime {get;set;} - - /// - /// Desc:换电结束时间 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="swap_end_time")] - public DateTime? SwapEndTime {get;set;} - - /// - /// Desc:换电结果;0-未知;1-成功;2-失败 - /// Default:0 - /// Nullable:True - /// - [SugarColumn(ColumnName="swap_result")] - public int? SwapResult {get;set;} - - /// - /// Desc:失败原因 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="fail_reason")] - public string FailReason {get;set;} - - /// - /// Desc:上传云平台状态;0-未上传;1-已上传 - /// Default:0 - /// Nullable:True - /// - [SugarColumn(ColumnName="cloud_report_status")] - public int? CloudReportStatus {get;set;} - - /// - /// Desc:创建人 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="created_by")] - public string CreatedBy {get;set;} - - /// - /// Desc:创建时间 - /// Default:CURRENT_TIMESTAMP - /// Nullable:True - /// - [SugarColumn(ColumnName="created_time")] - public DateTime? CreatedTime {get;set;} - - /// - /// Desc:更新人 - /// Default: - /// Nullable:True - /// - [SugarColumn(ColumnName="updated_by")] - public string UpdatedBy {get;set;} - - /// - /// Desc:更新时间 - /// Default:CURRENT_TIMESTAMP - /// Nullable:True - /// - [SugarColumn(ColumnName="updated_time")] - public DateTime? UpdatedTime {get;set;} - + public SwapOrder() + { + } + + /// + /// Desc:id + /// Default: + /// Nullable:False + /// + [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "id")] + public int Id { get; set; } + + /// + /// Desc:订单编号 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "sn")] + public string Sn { get; set; } + + /// + /// Desc:车牌号 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "vehicle_no")] + public string VehicleNo { get; set; } + + /// + /// Desc:车辆mac + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "vehicle_mac")] + public string VehicleMac { get; set; } + + /// + /// Desc:车辆vin码 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "vehicle_vin")] + public string VehicleVin { get; set; } + + /// + /// Desc:车辆进场时间 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "vehicle_enter_time")] + public DateTime? VehicleEnterTime { get; set; } + + /// + /// Desc:车辆离场时间 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "vehicle_leave_time")] + public DateTime? VehicleLeaveTime { get; set; } + + /// + /// Desc:换电开始时间 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "swap_begin_time")] + public DateTime? SwapBeginTime { get; set; } + + /// + /// Desc:换电结束时间 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "swap_end_time")] + public DateTime? SwapEndTime { get; set; } + + /// + /// Desc:换电结果;0-未知;1-成功;2-失败 + /// Default:0 + /// Nullable:True + /// + [SugarColumn(ColumnName = "swap_result")] + public int? SwapResult { get; set; } + + /// + /// Desc:失败原因 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "fail_reason")] + public string FailReason { get; set; } + + /// + /// Desc:上传云平台状态;0-未上传;1-已上传 + /// Default:0 + /// Nullable:True + /// + [SugarColumn(ColumnName = "cloud_report_status")] + public int? CloudReportStatus { get; set; } + + /// + /// Desc:创建人 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "created_by")] + public string CreatedBy { get; set; } + + /// + /// Desc:创建时间 + /// Default:CURRENT_TIMESTAMP + /// Nullable:True + /// + [SugarColumn(ColumnName = "created_time")] + public DateTime? CreatedTime { get; set; } + + /// + /// Desc:更新人 + /// Default: + /// Nullable:True + /// + [SugarColumn(ColumnName = "updated_by")] + public string UpdatedBy { get; set; } + + /// + /// Desc:更新时间 + /// Default:CURRENT_TIMESTAMP + /// Nullable:True + /// + [SugarColumn(ColumnName = "updated_time")] + public DateTime? UpdatedTime { get; set; } + /// + /// 云平台订单号 + /// + [SugarColumn(ColumnName = "cloud_sn")] + public string? CloudSn { get; set; } } -} +} \ No newline at end of file diff --git a/Entity/Entity.csproj b/Entity/Entity.csproj index e52d8c8..6f549b2 100644 --- a/Entity/Entity.csproj +++ b/Entity/Entity.csproj @@ -27,10 +27,6 @@ - - - - diff --git a/HybirdFrameworkCore/HybirdFrameworkCore.csproj b/HybirdFrameworkCore/HybirdFrameworkCore.csproj index c2fb8b7..ec6efa6 100644 --- a/HybirdFrameworkCore/HybirdFrameworkCore.csproj +++ b/HybirdFrameworkCore/HybirdFrameworkCore.csproj @@ -26,6 +26,8 @@ + + diff --git a/HybirdFrameworkCore/bin/Debug/net6.0/HybirdFrameworkCore.deps.json b/HybirdFrameworkCore/bin/Debug/net6.0/HybirdFrameworkCore.deps.json index 7e4eb2e..a230c49 100644 --- a/HybirdFrameworkCore/bin/Debug/net6.0/HybirdFrameworkCore.deps.json +++ b/HybirdFrameworkCore/bin/Debug/net6.0/HybirdFrameworkCore.deps.json @@ -18,6 +18,8 @@ "Swashbuckle.AspNetCore.Swagger": "6.5.0", "Swashbuckle.AspNetCore.SwaggerGen": "6.5.0", "Swashbuckle.AspNetCore.SwaggerUI": "6.5.0", + "Vse.Web.Serialization.ControlledSerializationJsonConverter": "1.0.3", + "WebApiContrib.Formatting.JavaScriptSerializer": "0.9.2", "log4net": "2.0.15" }, "runtime": { @@ -57,6 +59,18 @@ } } }, + "Microsoft.AspNet.WebApi.Client/4.0.20710": { + "dependencies": { + "Microsoft.Net.Http": "2.0.20710", + "Newtonsoft.Json": "13.0.3" + }, + "runtime": { + "lib/net40/System.Net.Http.Formatting.dll": { + "assemblyVersion": "4.0.0.0", + "fileVersion": "4.0.20710.0" + } + } + }, "Microsoft.CSharp/4.7.0": {}, "Microsoft.Extensions.ApiDescription.Server/6.0.5": {}, "Microsoft.Extensions.Configuration/7.0.0": { @@ -156,6 +170,7 @@ } } }, + "Microsoft.Net.Http/2.0.20710": {}, "Microsoft.NETCore.Platforms/2.0.0": {}, "Microsoft.OpenApi/1.2.3": { "runtime": { @@ -317,6 +332,25 @@ "fileVersion": "7.0.22.51805" } } + }, + "Vse.Web.Serialization.ControlledSerializationJsonConverter/1.0.3": { + "runtime": { + "lib/net45/Vse.Web.Serialization.dll": { + "assemblyVersion": "1.0.3.0", + "fileVersion": "1.0.3.0" + } + } + }, + "WebApiContrib.Formatting.JavaScriptSerializer/0.9.2": { + "dependencies": { + "Microsoft.AspNet.WebApi.Client": "4.0.20710" + }, + "runtime": { + "lib/net40/WebApiContrib.Formatting.JavaScriptSerializer.dll": { + "assemblyVersion": "0.0.0.0", + "fileVersion": "0.0.0.0" + } + } } } }, @@ -347,6 +381,13 @@ "path": "log4net/2.0.15", "hashPath": "log4net.2.0.15.nupkg.sha512" }, + "Microsoft.AspNet.WebApi.Client/4.0.20710": { + "type": "package", + "serviceable": true, + "sha512": "sha512-BwFtW0cGr8tg02XalvF8MmznOpYrhquD2eXWI0oF3LLSqLMFoFkb8Pmke/7SnqkiNc+YfsaUqdXEKbjhv1Ctrw==", + "path": "microsoft.aspnet.webapi.client/4.0.20710", + "hashPath": "microsoft.aspnet.webapi.client.4.0.20710.nupkg.sha512" + }, "Microsoft.CSharp/4.7.0": { "type": "package", "serviceable": true, @@ -424,6 +465,13 @@ "path": "microsoft.extensions.primitives/7.0.0", "hashPath": "microsoft.extensions.primitives.7.0.0.nupkg.sha512" }, + "Microsoft.Net.Http/2.0.20710": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OsB/5QO9tYJRLYIgBOhRl4Tssh3pw7+UAO9tMGMBg63f98GfjsniVIwLWRC0vcRr/F6HLP/NvRlHyGBhtD7Bmw==", + "path": "microsoft.net.http/2.0.20710", + "hashPath": "microsoft.net.http.2.0.20710.nupkg.sha512" + }, "Microsoft.NETCore.Platforms/2.0.0": { "type": "package", "serviceable": true, @@ -556,6 +604,20 @@ "sha512": "sha512-DaGSsVqKsn/ia6RG8frjwmJonfos0srquhw09TlT8KRw5I43E+4gs+/bZj4K0vShJ5H9imCuXupb4RmS+dBy3w==", "path": "system.text.json/7.0.0", "hashPath": "system.text.json.7.0.0.nupkg.sha512" + }, + "Vse.Web.Serialization.ControlledSerializationJsonConverter/1.0.3": { + "type": "package", + "serviceable": true, + "sha512": "sha512-eG8d1pOgu/espdIFfi9iAEE890oT9k5h/61RY9hpfu4+s1cozrZAkuwpHif6UadgKfexa5/BEVBZ8DNH1eA10w==", + "path": "vse.web.serialization.controlledserializationjsonconverter/1.0.3", + "hashPath": "vse.web.serialization.controlledserializationjsonconverter.1.0.3.nupkg.sha512" + }, + "WebApiContrib.Formatting.JavaScriptSerializer/0.9.2": { + "type": "package", + "serviceable": true, + "sha512": "sha512-OHJxwvqZhrpIw5fz7058vEiGHozBE/GGfnWMWrd/DnZC4fXwCZPKKqiyvzqq5KWQw/xf1jZ+e0ip/m6M2ZiEpw==", + "path": "webapicontrib.formatting.javascriptserializer/0.9.2", + "hashPath": "webapicontrib.formatting.javascriptserializer.0.9.2.nupkg.sha512" } } } \ No newline at end of file diff --git a/Repository/Station/BinInfoRepository.cs b/Repository/Station/BinInfoRepository.cs new file mode 100644 index 0000000..71580e6 --- /dev/null +++ b/Repository/Station/BinInfoRepository.cs @@ -0,0 +1,14 @@ +using Entity.DbModel.Station; +using HybirdFrameworkCore.Autofac.Attribute; +using SqlSugar; + +namespace Repository.Station; + +[Scope("SingleInstance")] +public class BinInfoRepository:BaseRepository +{ + + public BinInfoRepository(ISqlSugarClient sqlSugar) : base(sqlSugar) + { + } +} \ No newline at end of file diff --git a/Repository/Station/SwapAmtOrderRepository.cs b/Repository/Station/SwapAmtOrderRepository.cs new file mode 100644 index 0000000..6f8b939 --- /dev/null +++ b/Repository/Station/SwapAmtOrderRepository.cs @@ -0,0 +1,14 @@ +using Entity.DbModel.Station; +using HybirdFrameworkCore.Autofac.Attribute; +using SqlSugar; + +namespace Repository.Station; + +[Scope("SingleInstance")] +public class SwapAmtOrderRepository:BaseRepository +{ + + public SwapAmtOrderRepository(ISqlSugarClient sqlSugar) : base(sqlSugar) + { + } +} \ No newline at end of file diff --git a/Service/Execute/Api/CloudApi.cs b/Service/Execute/Api/CloudApi.cs index 8745576..8b5f749 100644 --- a/Service/Execute/Api/CloudApi.cs +++ b/Service/Execute/Api/CloudApi.cs @@ -1,6 +1,38 @@ +using Entity.DbModel.Station; +using log4net; +using Service.Execute.Enum; +using Service.Execute.Model; + namespace Service.Execute.Api; public class CloudApi { + /// + /// 云平台车辆认证 + /// + /// + /// + public static bool VehicleCheck(RfidReadModel rfidReadModel) + { + return true; + } + + /// + /// 上报换电步序到云端 + /// + /// + /// + public static void SendStateLog(SwapOrder swapOrder, InfoEnum.BusinessSwappingForCloudState state) + { + return; + } + /// + /// 上报tbox数据 + /// + + public static void UploadTBoxCarInfo(SwapOrder swapOrder, TboxCarInfoModel model) + { + return ; + } } \ No newline at end of file diff --git a/Service/Execute/Api/PlcApi.cs b/Service/Execute/Api/PlcApi.cs index 3f5b381..9350067 100644 --- a/Service/Execute/Api/PlcApi.cs +++ b/Service/Execute/Api/PlcApi.cs @@ -33,4 +33,16 @@ public class PlcApi //TODO:: return true; } + + /// + /// 写入口灯 + /// 红灯:1020 + /// 绿灯:1000 + /// + /// + /// + public static bool WriteEntranceLamp(int data) + { + return true; + } } \ No newline at end of file diff --git a/Service/Execute/Api/RfidApi.cs b/Service/Execute/Api/RfidApi.cs index 26f0802..992d961 100644 --- a/Service/Execute/Api/RfidApi.cs +++ b/Service/Execute/Api/RfidApi.cs @@ -1,6 +1,6 @@ using log4net; using Newtonsoft.Json; -using Swapping.Business.Rfid; +using Service.Execute.Model; namespace Service.Execute.Api; diff --git a/Service/Execute/Api/TboxApi.cs b/Service/Execute/Api/TboxApi.cs index b0817c4..ad18ddb 100644 --- a/Service/Execute/Api/TboxApi.cs +++ b/Service/Execute/Api/TboxApi.cs @@ -1,6 +1,65 @@ +using log4net; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Service.Execute.Model; + namespace Service.Execute.Api; public class TBoxApi { + private static readonly ILog Log = LogManager.GetLogger(typeof(TBoxApi)); + + //TODO::TBox 服务地址 + private static readonly string BASE_URL = "http://localhost:7243"; + + private static readonly HttpClient _httpClient = new HttpClient() + { + Timeout = TimeSpan.FromSeconds(60) + }; + + public static async Task GetCarInfo() + { + Log.Info("GetCarInfo"); + string url = BASE_URL + "/CarControl/getCarInfo"; + try + { + string s = await _httpClient.GetStringAsync(url); + TboxCarInfoModel? tboxCarInfoModel = null; + if (!String.IsNullOrWhiteSpace(s)) + { + tboxCarInfoModel = JsonConvert.DeserializeObject(s); + } + + Log.Info($"GetCarInfo resp = {tboxCarInfoModel}"); + return tboxCarInfoModel; + } + catch (Exception e) + { + Console.WriteLine(e); + return null; + } + } + public static async Task IsConnected() + { + Log.Info("IsConnected"); + string url = BASE_URL + "/CarControl/getCarInfo"; + try + { + string s = await _httpClient.GetStringAsync(url); + TboxCarInfoModel? tboxCarInfoModel = null; + if (!String.IsNullOrWhiteSpace(s)) + { + tboxCarInfoModel = JsonConvert.DeserializeObject(s); + } + + Log.Info($"GetCarInfo resp = {tboxCarInfoModel}"); + return tboxCarInfoModel.Connected; + } + catch (Exception e) + { + Console.WriteLine(e); + return false; + } + } } \ No newline at end of file diff --git a/Service/Execute/Enum/InfoEnum.cs b/Service/Execute/Enum/InfoEnum.cs index c93d07c..851daa6 100644 --- a/Service/Execute/Enum/InfoEnum.cs +++ b/Service/Execute/Enum/InfoEnum.cs @@ -45,7 +45,6 @@ public class InfoEnum [Remark("符合soc限制数量不足")] LessOfSoc, [Remark("结束充电大于3分钟的数量不足")] LessOf3Minute, [Remark("各种差数量不足")] LessOfMean, - [Remark("未被预约数量不足")] LessOfUnAmt, [Remark("预约电池异常")] AmtError, [Remark("电池捆绑选包失败")] GroupError, [Remark("无可用捆绑")] NoGroupError @@ -62,23 +61,22 @@ public class InfoEnum [Remark("换电中")] Swapping = 6, [Remark("预约失败")] Expire = 7, } - - public enum BusinessSwappingState : byte + + public enum BusinessSwappingForCloudState : byte { [Remark("未知")] UnKnown, [Remark("空闲")] Idle, - [Remark("RFID扫描完成")] ScanRfid, - [Remark("云平台验证完成")] CloudCheck, - [Remark("车辆到位")] CarInPosition, - [Remark("车辆准备完成(N档、手刹)")] CarPrepare, - [Remark("云平台启动换电完成")] CloudBeginSwap, - [Remark("车辆调整完成(下高压、下低压)")] CarAdjust, + [Remark("占位")] TakeUp, + [Remark("换电准备")] SwapReady, [Remark("开始换电")] BeginSwap, - [Remark("拆卸亏电包")] UnPack, - [Remark("安装满电包")] Pack, - [Remark("包安装完成")] PackFinish, - [Remark("车辆自检")] CarSelfCheck, - [Remark("换电完成(车辆驶离)")] SwapDone + [Remark("换电中")] Swapping, + [Remark("换电完成")] SwapFinish, + [Remark("换电中故障,等待修复")] SwappingErrWait, + [Remark("换电中故障,修复完成")] SwappingErrDone, + [Remark("换电暂停")] SwapPause, + [Remark("换电继续")] SwapContinue, + [Remark("换电完成(车辆未驶离)")] SwapDoneWithVel, + [Remark("换电完成(车辆驶离)")] SwapDoneWithoutVel } public enum AmtBatLockStatus : byte diff --git a/Service/Execute/Invoker.cs b/Service/Execute/Invoker.cs index c371974..9fbdf3b 100644 --- a/Service/Execute/Invoker.cs +++ b/Service/Execute/Invoker.cs @@ -45,11 +45,12 @@ public class Invoker return InvokeStatus.Done; } + public static InvokeStatus Invoke(string name, int duration, int times, Func cancel, Func done, Action doAction, - Action timeoutAction, bool isTimeOutExit, Action exceptionAction) + Action exceptionAction) { - int hvPwrOffTimes = 0; + int count = 0; while (!done()) { Log.Info($"begin {name}"); @@ -70,22 +71,12 @@ public class Invoker exceptionAction(); } - if (hvPwrOffTimes++ > times) - { - timeoutAction(); - Log.Info($" {name} timeout"); - if (isTimeOutExit) - { - return InvokeStatus.TimeOut; - } - } } Log.Info($" {name} done"); return InvokeStatus.Done; } - public static InvokeStatus Invoke(string name, int duration, int times, Func cancel, Func done, Action doAction, Action timeoutAction, bool isTimeOutExit, Action exceptionAction, int timeOutActionTime,InvokeStatus timeOutException) @@ -163,5 +154,6 @@ public enum InvokeStatus Cancel, TimeOut, Done, - Exception + Exception, + None } \ No newline at end of file diff --git a/Service/Execute/Model/RfidReadModel.cs b/Service/Execute/Model/RfidReadModel.cs index e4115f1..8788032 100644 --- a/Service/Execute/Model/RfidReadModel.cs +++ b/Service/Execute/Model/RfidReadModel.cs @@ -1,4 +1,4 @@ -namespace Swapping.Business.Rfid; +namespace Service.Execute.Model; public class RfidReadModel { diff --git a/Service/Execute/Model/SwapOrderBatteryInfo.cs b/Service/Execute/Model/SwapOrderBatteryInfo.cs new file mode 100644 index 0000000..1fc3337 --- /dev/null +++ b/Service/Execute/Model/SwapOrderBatteryInfo.cs @@ -0,0 +1,17 @@ +using Entity.DbModel.Station; +using NewLife.Common; +using Service.Execute.Enum; + +namespace Service.Execute.Model; + +public class SwapOrderBatteryInfo +{ + public bool isAmt; + public SwapAmtOrder swapAmtOrder; + public SwapOrderBattery SwapOrderBattery; + + public InfoEnum.SelectBinStatusInfo CanSwap; + + public BinInfo UpBinInfo; + public BinInfo InBinInfo; +} \ No newline at end of file diff --git a/Service/Execute/Model/TboxCarInfoModel.cs b/Service/Execute/Model/TboxCarInfoModel.cs new file mode 100644 index 0000000..0c45e60 --- /dev/null +++ b/Service/Execute/Model/TboxCarInfoModel.cs @@ -0,0 +1,27 @@ +namespace Service.Execute.Model; + +/// +/// 车辆数据 +/// +public class TboxCarInfoModel +{ + /// + /// 连接状态 + /// + public bool Connected { get; set; } + + /// + /// 车牌号 + /// + public string? CarNo { get; set; } + + /// + /// 度电数据 + /// + public TboxElecMsg? ElecMsg { get; set; } + + /// + /// 状态数据 + /// + public TboxHeartBeatMsg? HeartBeatMsg { get; set; } +} \ No newline at end of file diff --git a/Service/Execute/Model/TboxElecMsg.cs b/Service/Execute/Model/TboxElecMsg.cs new file mode 100644 index 0000000..42dbd10 --- /dev/null +++ b/Service/Execute/Model/TboxElecMsg.cs @@ -0,0 +1,84 @@ +using HybirdFrameworkCore.Autofac.Attribute; + +namespace Service.Execute.Model; + +public class TboxElecMsg +{ + /// + /// 车辆累计放电量 + /// + [Property(248, 24, scale: 0.01, round: 2)] + public double AccDischargeCount { get; set; } + + /// + /// 车辆累计回馈电量 + /// + [Property(272, 24, scale: 0.01, round: 2)] + public double AccFallbackCount { get; set; } + + /// + /// 车辆累计插枪充电量 + /// + [Property(296, 24, scale: 0.01, round: 2)] + public double AccChargeCount { get; set; } + + /// + /// 5 车辆累计综合能耗 + /// + [Property(320, 24, scale: 0.01, round: 2)] + public double AccKgce { get; set; } + + /// + /// 6 本次实时放电量 + /// + [Property(344, 24, scale: 0.01, round: 2)] + public double ThisTimeRealDischarge { get; set; } + + /// + /// 7 上一次结算放电量 + /// + [Property(368, 24, scale: 0.01, round: 2)] + public double LastTimeBalanceDischarge { get; set; } + + /// + /// 8 本次实时回馈电量 + /// + [Property(392, 24, scale: 0.01, round: 2)] + public double ThisTimeRealFeedbackPower { get; set; } + + /// + /// 9 上一次结算回馈电量 + /// + [Property(416, 24, scale: 0.01, round: 2)] + public double LastTimeBalanceFeedbackPower { get; set; } + + /// + /// 10 本次实时插枪充电量 + /// + [Property(440, 24, scale: 0.01, round: 2)] + public double ThisTimeRealChargeCount { get; set; } + + /// + /// 11 上一次结算插枪充电量 + /// + [Property(464, 24, scale: 0.01, round: 2)] + public double LastTimeBalanceChargeCount { get; set; } + + /// + /// 12 本次实时综合能耗 + /// + [Property(488, 24, scale: 0.01, round: 2)] + public double ThisTimeRealKgce { get; set; } + + /// + /// 13 上一次结算综合能耗 + /// + [Property(512, 24, scale: 0.01, round: 2)] + public double LastTimeBalanceKgce { get; set; } + + /// + /// 14 待结算电费电量 + /// + [Property(536, 24, scale: 0.01, round: 2)] + public double ElectricityToBeSettled { get; set; } +} \ No newline at end of file diff --git a/Service/Execute/Model/TboxHeartBeatMsg.cs b/Service/Execute/Model/TboxHeartBeatMsg.cs new file mode 100644 index 0000000..035a248 --- /dev/null +++ b/Service/Execute/Model/TboxHeartBeatMsg.cs @@ -0,0 +1,22 @@ +using HybirdFrameworkCore.Autofac.Attribute; + +namespace Service.Execute.Model; + +public class TboxHeartBeatMsg +{ + /// + /// 锁止状态 1 解锁状态 2 上锁状态 + /// + [Property(248, 8)] + public byte LockStatus { get; set; } + /// + /// 钥匙状态 0: OFF 1: ACC 2: ON 0xFF: 不支持 + /// + [Property(256, 8)] + public byte KeyStatus { get; set; } + /// + /// 电磁阀驱动状态 0:驱动关闭 1:驱动打开 + /// + [Property(264, 8)] + public byte SolenoidValveStatus { get; set; } +} \ No newline at end of file diff --git a/Service/Execute/Step/CarPrepareState.cs b/Service/Execute/Step/CarPrepareState.cs index 4db0463..0fb106a 100644 --- a/Service/Execute/Step/CarPrepareState.cs +++ b/Service/Execute/Step/CarPrepareState.cs @@ -1,14 +1,446 @@ -namespace Service.Execute.Step; +using AutoMapper; +using Entity.Constant; +using Entity.DbModel.Station; +using log4net; +using Repository.Station; +using Service.Execute.Api; +using Service.Execute.Enum; +using Service.Execute.Model; +using Service.Execute.StaticTools; +using Service.Execute.SwapException; +using Service.Init; +using Swapping.Business.Tech; -public class CarPrepareState: IState +namespace Service.Execute.Step; + +public class CarPrepareState : IState { + private readonly ILog _log = LogManager.GetLogger(typeof(CarPrepareState)); + + + private BinInfoRepository BinInfoRepository { get; set; } + + private SwapAmtOrderRepository AmtOrderRepository { get; set; } + + private SwapOrderBatteryRepository SwapOrderBatteryRepository { get; set; } + public StateResult Handle(SwappingStateMachine machine) { - + Thread.Sleep(500); + RfidReadModel? rfidReadModel = machine.RfidReadModel; + if (rfidReadModel == null) + { + _log.Error("rfid is null"); + return new StateResult() + { + SwappingState = SwappingState.StationReady + }; + } + + //云平台车辆认证 + var cloudCheckVel = CloudCheckVel(machine); + if (cloudCheckVel != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(cloudCheckVel, ExceptionReason.None); + } + + //检查tbox链接状态 + InvokeStatus checkTBoxConnect = CheckTBoxConnectFlag(machine); + if (checkTBoxConnect != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(checkTBoxConnect, ExceptionReason.None); + } + + //车辆本地验证 + InvokeStatus checkTBoxVelLocal = CheckTBoxVelLocalFlag(machine); + if (checkTBoxVelLocal != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(checkTBoxVelLocal, ExceptionReason.None); + } + + + //云端数据上报 + InvokeStatus cloudTBox = CloudTBoxFlag(machine); + if (cloudTBox != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(cloudTBox, ExceptionReason.None); + } + + SwappingStateMachine.ExceptionReason = ExceptionReason.None; + + //选包 + InvokeStatus selectPack = SelectPack(machine); + if (selectPack != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(selectPack, ExceptionReason.None); + } + + //车辆到位 + InvokeStatus carInPosition = CarInPosition(machine); + if (carInPosition != InvokeStatus.Done) + { + return SwappingStateMachine.ReturnWithInvokeErr(carInPosition, ExceptionReason.None); + } + return new StateResult() { - - SwappingState = SwappingState.StationReady + SwappingState = SwappingState.SelectPack + }; + } + + + /// + /// 车辆到位 + /// + /// + public InvokeStatus CarInPosition(SwappingStateMachine machine) + { + return Invoker.Invoke("check CarInPosition", 500, 50, machine.IsCanceled, + () => SwappingStateMachine.VehiclesInPlaceFlag, () => + { + var result = TBoxApi.GetCarInfo(); + TboxCarInfoModel tboxCarInfoModel = result.Result; + + if (tboxCarInfoModel.HeartBeatMsg.KeyStatus == 0) + { + SwappingStateMachine.VehiclesInPlaceFlag = true; + //写入口等 :红灯 + if (PlcApi.WriteEntranceLamp(1020)) + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoCarInPosition.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoCarInPosition); + SwappingStateMachine.VehiclesInPlaceFlag = true; + } + } + }, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.CarInPositionError; + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout); + }, false, () => { } + , 20, InvokeStatus.None); + } + + /// + /// 云平台车辆认证 + /// + /// + public InvokeStatus CloudCheckVel(SwappingStateMachine machine) + { + return Invoker.Invoke("cloud check vehicle", 500, 20, machine.IsCanceled, + () => SwappingStateMachine.CloudVelCheckFlag, () => + { + if (BaseEnumExtensions.GetEnumByCode( + int.Parse(StaticStationInfo.StationModel)) == StationConstant.StationModel.Remote) + { + bool flag = CloudApi.VehicleCheck(machine.RfidReadModel); + + if (!flag) + { + _log.Info("cloud check vehicle error"); + } + else + { + //置为换电准备中 ,上报换电准备中 + SwappingStateMachine.BusinessSwappingForCloudState = + InfoEnum.BusinessSwappingForCloudState.SwapReady; + SwappingStateMachine.ExceptionReason = ExceptionReason.None; + _log.Info("cloud check vehicle done"); + SwappingStateMachine.CloudVelCheckFlag = true; + machine.LedTool.WriteProgramContent("换电准备中:云平台车辆验证完成"); + CloudApi.SendStateLog(machine.SwapOrder, SwappingStateMachine.BusinessSwappingForCloudState); + SwappingStateMachine.CloudVelCheckFlag = true; + } + } + else + { + SwappingStateMachine.CloudVelCheckFlag = true; + } + }, () => + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCloudCheck.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCloudCheck); + }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.CloudCheckError; } + , 20, InvokeStatus.None); + } + + + /// + /// 检查tbox连接状态 + /// + /// + public InvokeStatus CheckTBoxConnectFlag(SwappingStateMachine machine) + { + return Invoker.Invoke("check TBox connect", 1000, 20, machine.IsCanceled, + () => SwappingStateMachine.TBoxConnectFlag, () => + { + Task result = TBoxApi.IsConnected(); + bool isConnect = result.Result; + if (isConnect) + { + SwappingStateMachine.TBoxConnectFlag = true; + } + }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ConnTBoxError; }, false, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.ConnTBoxError; + } + , 10, InvokeStatus.None); + } + + + /// + /// 车辆本地验证:车牌校验 + /// + /// + public InvokeStatus CheckTBoxVelLocalFlag(SwappingStateMachine machine) + { + return Invoker.Invoke("check TBox VelLocal", 1000, 20, machine.IsCanceled, + () => SwappingStateMachine.TBoxLocalCheckFlag, () => + { + Task carInfo = TBoxApi.GetCarInfo(); + var tBoxCarInfoModel = carInfo.Result; + //TODO::不知道Tbox给的CardNo是什么 + if (tBoxCarInfoModel.CarNo.Trim().Equals(machine.RfidReadModel.VelNo.Trim())) + { + SwappingStateMachine.TBoxLocalCheckFlag = true; + } + }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.LocalCheckVarError; }, true, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.LocalCheckVarError; + } + , 3, InvokeStatus.TimeOut); + } + + + /// + /// 蓝牙数据云平台上报 + /// + /// + public InvokeStatus CloudTBoxFlag(SwappingStateMachine machine) + { + return Invoker.Invoke("cloud TBox upload", 500, 20, machine.IsCanceled, + () => SwappingStateMachine.CloudTBoxFlag, () => + { + Task result = TBoxApi.GetCarInfo(); + TboxCarInfoModel tBoxCarInfoModel = result.Result; + machine.TBoxCarInfoModel = tBoxCarInfoModel; + if (tBoxCarInfoModel != null) + { + if (tBoxCarInfoModel.Connected) + { + //将数据上报云平台 + CloudApi.UploadTBoxCarInfo(machine.SwapOrder, machine.TBoxCarInfoModel); + } + } + }, () => { machine.LedTool?.WriteProgramContent("车机蓝牙车辆数据上报异常,请联系站务人员"); }, false, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.CloudCarDataUploadError; + } + , 20, InvokeStatus.None); + } + + /// + /// 选包: + /// 有预约单: 获取预约单的电池 + /// 无预约单: + /// 1.仓位状态:启动 + /// 2.电池在位 + /// 3.充电状态:不在充电中 + /// 4.未锁定 + /// 5.最后一次结束充电时间> () + /// 6.soc >() + /// + /// + public InvokeStatus SelectPack(SwappingStateMachine machine) + { + SwapAmtOrder? swapAmtOrder = + AmtOrderRepository.QueryByClause(i => i.Status == 1 && i.VehicleNo.Equals(machine.TBoxCarInfoModel.CarNo)); + + + return Invoker.Invoke("selectPack", 500, 20, machine.IsCanceled, + () => SwappingStateMachine.SelectPackFlag, () => + + { + SwapOrderBatteryInfo orderBatteryInfo = null; + if (swapAmtOrder != null) + { + orderBatteryInfo = SelectPackArm(swapAmtOrder); + } + else + { + orderBatteryInfo = SelectPackNotArm(); + } + + if (orderBatteryInfo.CanSwap != InfoEnum.SelectBinStatusInfo.Success) + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorSelectPack.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorSelectPack); + Thread.Sleep(1000 * 3); + _log.Info($"SelectPack error CanSwap={machine.SwapOrderBatteryInfo.CanSwap}"); + } + else + { + //选包成功 + LockBinAndUpdateAmt(orderBatteryInfo); + machine.SwapOrderBatteryInfo = orderBatteryInfo; + SaveSwapBattery(machine); + SwappingStateMachine.SelectPackFlag = true; + } + }, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.SelectPackError; }); + } + + private void SaveSwapBattery(SwappingStateMachine machine) + { + BinInfo UpBin = machine.SwapOrderBatteryInfo.UpBinInfo; + BinInfo InBin = machine.SwapOrderBatteryInfo.InBinInfo; + SwapOrderBattery swapOrderBattery = new SwapOrderBattery() + { + SwapOrderSn = machine.SwapOrder.Sn, + UpBatterySoc = UpBin.Soc, + UpBatteryNo = UpBin.BatteryNo, + UpBatterySoe = UpBin.Soe, + UpBatteryBinNo = int.Parse(UpBin.No), + DownBatteryBinNo = int.Parse(InBin.No), }; + SwapOrderBatteryRepository.Insert(swapOrderBattery); + } + + /// + /// 1.锁仓 + /// 2.更改预约单 + /// + private void LockBinAndUpdateAmt(SwapOrderBatteryInfo orderBatteryInfo) + { + var configBinInfo = + new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); + IMapper mapperBinInfo = configBinInfo.CreateMapper(); + BinInfo dbBinInfo = mapperBinInfo.Map(orderBatteryInfo.UpBinInfo); + + dbBinInfo.AmtLock = "1"; + BinInfoRepository.Update(dbBinInfo); + if (!orderBatteryInfo.isAmt) + { + return; + } + + var configAmt = + new MapperConfiguration(cfg => cfg.CreateMap().ReverseMap()); + IMapper mapperAmt = configAmt.CreateMapper(); + SwapAmtOrder swapAmtOrder = mapperAmt.Map(orderBatteryInfo.swapAmtOrder); + swapAmtOrder.Status = 6; + AmtOrderRepository.Update(swapAmtOrder); + } + + /// 1.仓位状态:启动 + /// 2.电池在位 + /// 3.充电状态:不在充电中 + /// 4.未锁定 + /// 5.最后一次结束充电时间> () + /// 6.soc >() + /** + * && i.ChargeStatus == 2 + && i.AmtLock == "0" + && new TimeSpan(DateTime.Now.Ticks - + i.LastChargeFinishTime.ToDateTime().Ticks) + .TotalMinutes > StaticStationInfo.SwapFinishChargeTime + && i.Soc > StaticStationInfo.Soc + */ + private SwapOrderBatteryInfo SelectPackNotArm() + { + SwapOrderBatteryInfo orderBatteryInfo = new SwapOrderBatteryInfo(); + UpBin(orderBatteryInfo); + if (orderBatteryInfo.CanSwap != InfoEnum.SelectBinStatusInfo.Success) + { + return orderBatteryInfo; + } + + InBin(orderBatteryInfo); + + return orderBatteryInfo; + } + + private SwapOrderBatteryInfo SelectPackArm(SwapAmtOrder swapAmtOrder) + { + SwapOrderBatteryInfo orderBatteryInfo = new SwapOrderBatteryInfo(); + orderBatteryInfo.swapAmtOrder = swapAmtOrder; + orderBatteryInfo.isAmt = true; + BinInfo UpBin = BinInfoRepository.QueryByClause(i => i.No.Equals(swapAmtOrder.AmtBinNoList)); + bool CanSwap = UpBin.Exists == 1 && UpBin.Status == 1 && UpBin.ChargeStatus == 2 + && UpBin.AmtLock == "1" && new TimeSpan(DateTime.Now.Ticks - + UpBin.LastChargeFinishTime.ToDateTime() + .Ticks) + .TotalMinutes > int.Parse(StaticStationInfo.SwapFinishChargeTime) && + UpBin.Soc > int.Parse(StaticStationInfo.SwapSoc); + if (!CanSwap) + { + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.AmtError; + + return orderBatteryInfo; + } + + orderBatteryInfo.UpBinInfo = UpBin; + InBin(orderBatteryInfo); + return orderBatteryInfo; + } + + /// + /// 取电池判断 + /// + /// + private void UpBin(SwapOrderBatteryInfo orderBatteryInfo) + { + List list = + BinInfoRepository.QueryListByClause(i => i.Exists == 1 && i.Status == 1 && i.AmtLock == "0"); + if (list.Count <= 0) + { + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.NoBattery; + return; + } + + list = list.Where(i => i.ChargeStatus == 2).ToList(); + if (list.Count <= 0) + { + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOfFinishCharging; + return; + } + + + list = list.Where(i => i.Soc > int.Parse(StaticStationInfo.SwapSoc)).ToList(); + if (list.Count <= 0) + { + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOfSoc; + return; + } + + list = list.Where(i => new TimeSpan(DateTime.Now.Ticks - + i.LastChargeFinishTime.ToDateTime().Ticks) + .TotalMinutes > int.Parse(StaticStationInfo.SwapFinishChargeTime)).ToList(); + if (list.Count <= 0) + { + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOf3Minute; + return; + } + + orderBatteryInfo.UpBinInfo = list[0]; + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.Success; + } + + /// + /// 放电池判断 + /// + /// + private void InBin(SwapOrderBatteryInfo orderBatteryInfo) + { + List list = + BinInfoRepository.QueryListByClause(i => i.Exists == 1 && i.Status == 1 && i.AmtLock == "0" + && i.Exists == 0); + if (list.Count <= 0) + { + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.LessOfEmptyBin; + return; + } + + orderBatteryInfo.InBinInfo = list[0]; + orderBatteryInfo.CanSwap = InfoEnum.SelectBinStatusInfo.Success; } } \ No newline at end of file diff --git a/Service/Execute/Step/CloudSendOutSwapState.cs b/Service/Execute/Step/CloudSendOutSwapState.cs new file mode 100644 index 0000000..b09e25f --- /dev/null +++ b/Service/Execute/Step/CloudSendOutSwapState.cs @@ -0,0 +1,52 @@ +using Entity.Constant; + +namespace Service.Execute.Step; + +/// +/// 云平台下发换电 +/// +public class CloudSendOutSwapState: IState +{ + public StateResult Handle(SwappingStateMachine machine) + { + + return new StateResult() + { + + SwappingState = SwappingState.StationReady + }; + } + + + /// + /// 等待云平台下发换电 + /// + /// + /*public InvokeStatus CloudSendOutSwap(SwappingStateMachine machine) + { + return Invoker.Invoke("check CarInPosition", 500, 50, machine.IsCanceled, + () => SwappingStateMachine.VehiclesInPlaceFlag, () => + { + var result = TBoxApi.GetCarInfo(); + TboxCarInfoModel tboxCarInfoModel = result.Result; + + if (tboxCarInfoModel.HeartBeatMsg.KeyStatus == 0) + { + SwappingStateMachine.VehiclesInPlaceFlag = true; + //写入口等 :红灯 + if (PlcApi.WriteEntranceLamp(1020)) + { + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.InfoCarInPosition.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.InfoCarInPosition); + SwappingStateMachine.VehiclesInPlaceFlag = true; + } + } + }, () => + { + SwappingStateMachine.ExceptionReason = ExceptionReason.CarInPositionError; + machine.LedTool?.WriteProgramContent(InfoEnum.SwapInfo.ErrorCarInPositionTimeout.GetLed()); + SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorCarInPositionTimeout); + }, false, () => { } + , 20, InvokeStatus.None); + }*/ +} \ No newline at end of file diff --git a/Service/Execute/Step/SelectPackState.cs b/Service/Execute/Step/SelectPackState.cs deleted file mode 100644 index 6469a08..0000000 --- a/Service/Execute/Step/SelectPackState.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Service.Execute.Step; - -public class SelectPackState: IState -{ - public StateResult Handle(SwappingStateMachine machine) - { - - return new StateResult() - { - - SwappingState = SwappingState.StationReady - }; - } -} \ No newline at end of file diff --git a/Service/Execute/Step/StationReadyState.cs b/Service/Execute/Step/StationReadyState.cs index 6832ae6..edc70bb 100644 --- a/Service/Execute/Step/StationReadyState.cs +++ b/Service/Execute/Step/StationReadyState.cs @@ -2,16 +2,17 @@ using Entity.Constant; using Entity.DbModel.Station; using log4net; +using Microsoft.OpenApi.Extensions; using Microsoft.VisualBasic; using Newtonsoft.Json; using Repository.Station; using Service.Execute.Api; using Service.Execute.Enum; +using Service.Execute.Model; using Service.Execute.StaticTools; using Service.Execute.SwapException; using Service.Init; using Swapping.Business.Common; -using Swapping.Business.Rfid; using Swapping.Business.Tech; namespace Service.Execute.Step; @@ -28,7 +29,7 @@ public class StationReadyState : IState _log.Info($"'goto stationReady"); machine.Reset(); - SwappingStateMachine.BusinessSwappingState = InfoEnum.BusinessSwappingState.Idle; + SwappingStateMachine.BusinessSwappingForCloudState = InfoEnum.BusinessSwappingForCloudState.Idle; SwappingStateMachine.BusinessSwappingStateUpdateTime = DateTime.Now; //判断换电站是否具备换电条件 @@ -78,20 +79,29 @@ public class StationReadyState : IState public InvokeStatus PlcIsRemote(SwappingStateMachine machine) { - return Invoker.Invoke("check plc remote", 1000, 5, machine.IsCanceled, PlcApi.IsRemote, + bool isRemote = false; + return Invoker.Invoke("check plc remote", 1000, 5, machine.IsCanceled, () => isRemote, () => { - //LED显示-欢迎光临_换电站点_正在营业(三行展示) - string welcomeContent = "欢迎光临" + StaticStationInfo.StationName + "正在营业"; - - machine.LedTool?.WriteContent(welcomeContent); + if (PlcApi.IsRemote()) + { + //写入口灯绿灯 + if (PlcApi.WriteEntranceLamp(1000)) + { + //LED显示-欢迎光临_换电站点_正在营业 + string welcomeContent = "欢迎光临" + StaticStationInfo.StationName + "正在营业"; + + machine.LedTool?.WriteContent(welcomeContent); + isRemote = true; + } + } }, - () => { }, false); + () => { }, true); } public InvokeStatus EntranceRadar(SwappingStateMachine machine) { - return Invoker.Invoke("wait entrance radar", 1000, 1, machine.IsCanceled, + return Invoker.Invoke("wait entrance radar", 1000, 5, machine.IsCanceled, () => SwappingStateMachine.RadarInFlag, () => { if (!PlcApi.EntranceRadar()) @@ -128,7 +138,8 @@ public class StationReadyState : IState { machine.LedTool.WriteProgramContent(InfoEnum.SwapInfo.ErrorReadRfid.GetLed()); SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorReadRfid); - }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ReadRfidError; }); + }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ReadRfidError; } + , 1, InvokeStatus.TimeOut); } /// @@ -139,13 +150,19 @@ public class StationReadyState : IState /// private bool IsAutoSwapping() { - var statusDes = StationConstant.EnumExtensions.GetDescription(StaticStationInfo.StationStatus); + var statusDes = + BaseEnumExtensions.GetEnumDescriptionByCode( + int.Parse(StaticStationInfo.StationStatus)); _log.Info($"换电站处于{statusDes}状态"); - var wayDes = StationConstant.EnumExtensions.GetDescription(StaticStationInfo.StationWay); + var wayDes = + BaseEnumExtensions.GetEnumDescriptionByCode( + int.Parse(StaticStationInfo.StationWay)); _log.Info($"换电站处于{wayDes}模式"); - if (StationConstant.StationStatus.Run == StaticStationInfo.StationStatus - && StationConstant.StationWay.Auto == StaticStationInfo.StationWay) + if (StationConstant.StationStatus.Run == + BaseEnumExtensions.GetEnumByCode(int.Parse(StaticStationInfo.StationStatus)) + && StationConstant.StationWay.Auto == + BaseEnumExtensions.GetEnumByCode(int.Parse(StaticStationInfo.StationWay))) { return true; } @@ -177,9 +194,8 @@ public class StationReadyState : IState _log.Info($"read rfid={JsonConvert.SerializeObject(machine.RfidReadModel)}"); SwappingStateMachine.ExceptionReason = ExceptionReason.None; - SwappingStateMachine.BusinessSwappingState = InfoEnum.BusinessSwappingState.ScanRfid; SwappingStateMachine.BusinessSwappingStateUpdateTime = DateTime.Now; - _log.Info($"BusinessSwappingState={SwappingStateMachine.BusinessSwappingState}"); + _log.Info($"BusinessSwappingForCloudState={SwappingStateMachine.BusinessSwappingForCloudState}"); machine.SwapOrder = SaveOrder(BuildOrder(machine.RfidReadModel)); diff --git a/Service/Execute/SwapException/ExceptionReason.cs b/Service/Execute/SwapException/ExceptionReason.cs index 26d8aa2..7dea255 100644 --- a/Service/Execute/SwapException/ExceptionReason.cs +++ b/Service/Execute/SwapException/ExceptionReason.cs @@ -8,11 +8,11 @@ namespace Service.Execute.SwapException; { None, ReadRfidError, - OpenBarrierError, - ConnVbleError, + ConnTBoxError, CarStateCheckError, CloudCheckError, - CloudVbleDataError, + LocalCheckVarError, + CloudCarDataUploadError, CarInPositionError, CloudSendSwapError, SelectPackError, diff --git a/Service/Execute/SwappingStateMachine.cs b/Service/Execute/SwappingStateMachine.cs index 66d365e..3028612 100644 --- a/Service/Execute/SwappingStateMachine.cs +++ b/Service/Execute/SwappingStateMachine.cs @@ -2,11 +2,11 @@ using log4net; using Newtonsoft.Json; using Service.Execute.Enum; +using Service.Execute.Model; using Service.Execute.StaticTools; using Service.Execute.Step; using Service.Execute.SwapException; using Service.Execute.Tech; -using Swapping.Business.Rfid; namespace Service.Execute; @@ -22,16 +22,21 @@ public class SwappingStateMachine : IDisposable private Dictionary Dictionary = new Dictionary(); private StateResult _result = new StateResult() { SwappingState = SwappingState.Begin }; - public static InfoEnum.BusinessSwappingState BusinessSwappingState = InfoEnum.BusinessSwappingState.UnKnown; + //给云平台的实时状态 + public static InfoEnum.BusinessSwappingForCloudState BusinessSwappingForCloudState = + InfoEnum.BusinessSwappingForCloudState.UnKnown; public static DateTime BusinessSwappingStateUpdateTime = DateTime.Now; public static ExceptionReason ExceptionReason = ExceptionReason.None; public RfidReadModel? RfidReadModel=null; + public TboxCarInfoModel? TBoxCarInfoModel = null; public SwapOrder? SwapOrder=null; + public SwapOrderBatteryInfo SwapOrderBatteryInfo = null; + #region 小步状态 @@ -46,7 +51,13 @@ public class SwappingStateMachine : IDisposable public static bool CloudVelCheckFlag = false; //Tbox连接 - public static bool TBoxConnectionFlag = false; + public static bool TBoxConnectFlag = false; + + //Tbox本地校验 + public static bool TBoxLocalCheckFlag = false; + + //Tbox数据上传 + public static bool CloudTBoxFlag = false; //选包 public static bool SelectPackFlag = false; @@ -102,7 +113,7 @@ public class SwappingStateMachine : IDisposable Dictionary[SwappingState.Begin] = new BeginState(); Dictionary[SwappingState.StationReady] = new StationReadyState(); Dictionary[SwappingState.CarPrepare] = new CarPrepareState(); - Dictionary[SwappingState.SelectPack] = new SelectPackState(); + Dictionary[SwappingState.SelectPack] = new CloudSendOutSwapState(); Dictionary[SwappingState.CarCtrl] = new CarCtrlState(); Dictionary[SwappingState.DoSwapping] = new DoSwappingState(); Dictionary[SwappingState.SwapDone] = new SwapDoneState(); diff --git a/Service/Init/StaticStationInfo.cs b/Service/Init/StaticStationInfo.cs index bb18b56..d06fec7 100644 --- a/Service/Init/StaticStationInfo.cs +++ b/Service/Init/StaticStationInfo.cs @@ -11,23 +11,49 @@ namespace Service.Init; /// public class StaticStationInfo { - public static StationConstant.StationStatus StationStatus; - public static StationConstant.StationWay StationWay; - - public static StationConstant.StationModel StationModel; + public static string StationStatus + { + get => Resolve(StationParamConst.StationStatus); + set => Set(StationParamConst.StationStatus, value); + } + public static string StationWay + { + get => Resolve(StationParamConst.StationWay); + set => Set(StationParamConst.StationWay, value); + } + public static string StationModel + { + get => Resolve(StationParamConst.StationModel); + set => Set(StationParamConst.StationModel, value); + } + public static string StationName { get => Resolve(StationParamConst.StationName); set => Set(StationParamConst.StationName, value); } + + public static string StationNo { get => Resolve(StationParamConst.StationNo); set => Set(StationParamConst.StationNo, value); } + + public static string SwapFinishChargeTime + { + get => Resolve(StationParamConst.SwapFinishChargeTime); + set => Set(StationParamConst.SwapFinishChargeTime, value); + } + + public static string SwapSoc + { + get => Resolve(StationParamConst.SwapSoc); + set => Set(StationParamConst.SwapSoc, value); + } #region cloud diff --git a/Service/Station/StationParamConst.cs b/Service/Station/StationParamConst.cs index 822e1a3..6e0b84c 100644 --- a/Service/Station/StationParamConst.cs +++ b/Service/Station/StationParamConst.cs @@ -5,6 +5,15 @@ public class StationParamConst public static readonly string StationNo = "Station.StationNo"; public static readonly string StationName = "Station.StationName"; + //选包策略中最后结束充电时间需要>此值 + public static readonly string SwapFinishChargeTime = "Station.SwapFinishChargeTime"; + //选包策略换电Soc + public static readonly string SwapSoc = "Station.SwapSoc"; + + + public static readonly string StationStatus = "Station.StationStatus"; + public static readonly string StationWay = "Station.StationWay"; + public static readonly string StationModel = "Station.StationModel"; #region cloud param public static readonly string CloudServerIp = "Cloud.CloudServerIp"; diff --git a/WebStarter/Controllers/Test/GenController.cs b/WebStarter/Controllers/Test/GenController.cs index cee0a5d..628777a 100644 --- a/WebStarter/Controllers/Test/GenController.cs +++ b/WebStarter/Controllers/Test/GenController.cs @@ -1,3 +1,4 @@ +using Entity.DbModel.Station; using Microsoft.AspNetCore.Mvc; using Repository.Station; using SqlSugar; @@ -30,17 +31,17 @@ public class GenController : ControllerBase .FormatFileName(it => ToPascalCase(it)) //格式化文件名(文件名和表名不一样情况) .FormatClassName(it => ToPascalCase(it)) //格式化类名 (类名和表名不一样的情况) .FormatPropertyName(it => ToPascalCase(it)) //格式化属性名 (属性名和字段名不一样情况) - .CreateClassFile("D:\\lxw\\work\\pro\\c#\\hn_back_main\\Entity\\DbModel\\Station", + .CreateClassFile("D:\\lxw\\work\\pro\\c#\\hn_back_main\\Entity\\DbModel\\Station\\Temp", "Entity.DbModel.Station"); Console.WriteLine("生成完毕"); } - /*[HttpGet("test115")] + [HttpGet("test115")] public void Test115() { - _batteryGroupRepository.Insert(new List() + /*_batteryGroupRepository.Insert(new List() { new BatteryGroup() { @@ -52,17 +53,25 @@ public class GenController : ControllerBase BatteryNo = "2", Group = 2, }, - }); - List batteryGroups = _batteryGroupRepository.Query(); - BatteryGroup batteryGroup = batteryGroups[0]; + });*/ + BatteryGroup batteryGroups = _batteryGroupRepository.QueryByClause(i=>i.Group==1); + /*BatteryGroup batteryGroup = batteryGroups[0]; _batteryGroupRepository.Delete(batteryGroup); BatteryGroup batteryGroup1 = batteryGroups[1]; batteryGroup1.Group = 3; - _batteryGroupRepository.Update(batteryGroup1); + _batteryGroupRepository.Update(batteryGroup1);*/ + if (batteryGroups == null) + { + Console.WriteLine(); + } + else + { + Console.WriteLine(); + } Console.WriteLine("测试完毕"); - }*/ + } static string ToPascalCase(string input)