diff --git a/Entity/Api/Req/AddSwapOrderReq.cs b/Entity/Api/Req/AddSwapOrderReq.cs
index e5600cd..02d7951 100644
--- a/Entity/Api/Req/AddSwapOrderReq.cs
+++ b/Entity/Api/Req/AddSwapOrderReq.cs
@@ -1,8 +1,4 @@
-using System.ComponentModel.DataAnnotations;
-using Entity.DbModel.Station;
-using SqlSugar;
-
-namespace Entity.Api.Resp
+namespace Entity.Api.Req
{
///
///新增换电订单
@@ -17,28 +13,28 @@ namespace Entity.Api.Resp
/// Default:
/// Nullable:True
///
- public string Sn {get;set;}
+ public string? Sn {get;set;}
///
/// Desc:车牌号
/// Default:
/// Nullable:True
///
- public string VehicleNo {get;set;}
+ public string? VehicleNo {get;set;}
///
/// Desc:车辆mac
/// Default:
/// Nullable:True
///
- public string VehicleMac {get;set;}
+ public string? VehicleMac {get;set;}
///
/// Desc:车辆vin码
/// Default:
/// Nullable:True
///
- public string VehicleVin {get;set;}
+ public string? VehicleVin {get;set;}
///
/// Desc:车辆进场时间
@@ -80,7 +76,7 @@ namespace Entity.Api.Resp
/// Default:
/// Nullable:True
///
- public string FailReason {get;set;}
+ public string? FailReason {get;set;}
///
/// Desc:上传云平台状态;0-未上传;1-已上传
@@ -94,7 +90,7 @@ namespace Entity.Api.Resp
/// Default:
/// Nullable:True
///
- public string CreatedBy {get;set;}
+ public string? CreatedBy {get;set;}
///
/// Desc:创建时间
@@ -108,7 +104,7 @@ namespace Entity.Api.Resp
/// Default:
/// Nullable:True
///
- public string UpdatedBy {get;set;}
+ public string? UpdatedBy {get;set;}
///
/// Desc:更新时间
diff --git a/Entity/Api/Req/ModifySwapOrderReq.cs b/Entity/Api/Req/ModifySwapOrderReq.cs
index a6609cd..7519375 100644
--- a/Entity/Api/Req/ModifySwapOrderReq.cs
+++ b/Entity/Api/Req/ModifySwapOrderReq.cs
@@ -1,8 +1,6 @@
using System.ComponentModel.DataAnnotations;
-using Entity.DbModel.Station;
-using SqlSugar;
-namespace Entity.Api.Resp
+namespace Entity.Api.Req
{
///
///新增换电订单
diff --git a/Entity/Api/Req/QueryChargeOrderReq.cs b/Entity/Api/Req/QueryChargeOrderReq.cs
index 2811f15..87128f0 100644
--- a/Entity/Api/Req/QueryChargeOrderReq.cs
+++ b/Entity/Api/Req/QueryChargeOrderReq.cs
@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations;
+using HybirdFrameworkCore.Entity;
using SqlSugar;
namespace Entity.Api.Req
@@ -6,7 +7,7 @@ namespace Entity.Api.Req
///
///查询充电订单
///
- public class QueryChargeOrderReq
+ public class QueryChargeOrderReq :QueryPageModel
{
@@ -16,14 +17,14 @@ namespace Entity.Api.Req
/// Default:
/// Nullable:True
///
- public string Sn {get;set;}
+ public string? Sn {get;set;}
///
/// Desc:电池编号
/// Default:
/// Nullable:True
///
- public string BatteryNo {get;set;}
+ public string? BatteryNo {get;set;}
@@ -32,14 +33,14 @@ namespace Entity.Api.Req
/// Default:
/// Nullable:True
///
- public string ChargerNo {get;set;}
+ public string? ChargerNo {get;set;}
///
/// Desc:充电枪编号
/// Default:
/// Nullable:True
///
- public string ChargerGunNo {get;set;}
+ public string? ChargerGunNo {get;set;}
///
/// Desc:充电开始时间
@@ -74,7 +75,7 @@ namespace Entity.Api.Req
/// Default:
/// Nullable:True
///
- public string ChargeTimeCount {get;set;}
+ public string? ChargeTimeCount {get;set;}
///
/// Desc:充电电量
@@ -118,14 +119,14 @@ namespace Entity.Api.Req
/// Default:
/// Nullable:True
///
- public string ElecPriceModelVersion {get;set;}
+ public string? ElecPriceModelVersion {get;set;}
///
/// Desc:换电订单编号
/// Default:
/// Nullable:True
///
- public string SwapOrderSn {get;set;}
+ public string? SwapOrderSn {get;set;}
///
/// Desc:上传云平台状态;0-未上传;1-已上传
diff --git a/Entity/Api/Req/QuerySwapOrderPageReq.cs b/Entity/Api/Req/QuerySwapOrderPageReq.cs
index a51554d..3344aed 100644
--- a/Entity/Api/Req/QuerySwapOrderPageReq.cs
+++ b/Entity/Api/Req/QuerySwapOrderPageReq.cs
@@ -9,28 +9,28 @@ public class QuerySwapOrderPageReq : QueryPageModel
/// Default:
/// Nullable:True
///
- public string Sn { get; set; }
+ public string? Sn { get; set; }
///
/// Desc:车牌号
/// Default:
/// Nullable:True
///
- public string VehicleNo { get; set; }
+ public string? VehicleNo { get; set; }
///
/// Desc:车辆mac
/// Default:
/// Nullable:True
///
- public string VehicleMac { get; set; }
+ public string? VehicleMac { get; set; }
///
/// Desc:车辆vin码
/// Default:
/// Nullable:True
///
- public string VehicleVin { get; set; }
+ public string? VehicleVin { get; set; }
///
diff --git a/Entity/Api/Resp/ChargeOrderResp.cs b/Entity/Api/Resp/ChargeOrderResp.cs
index 981a0dc..473d33c 100644
--- a/Entity/Api/Resp/ChargeOrderResp.cs
+++ b/Entity/Api/Resp/ChargeOrderResp.cs
@@ -41,7 +41,7 @@ namespace Entity.Api.Resp
/// Default:
/// Nullable:True
///
- public string ChargerNo {get;set;}
+ public string? ChargerNo {get;set;}
///
/// Desc:充电枪编号
diff --git a/Entity/Constant/StationConstant.cs b/Entity/Constant/StationConstant.cs
new file mode 100644
index 0000000..9443856
--- /dev/null
+++ b/Entity/Constant/StationConstant.cs
@@ -0,0 +1,63 @@
+using System.ComponentModel;
+using System.Reflection;
+
+namespace Entity.Constant;
+
+public class StationConstant
+{
+ ///
+ /// 换电站状态: 1:营运中 2:歇业中 3:设备维护状态 4:暂停营业
+ ///
+ public enum StationStatus
+ {
+
+ [Description("营运中")]
+ Run=1,
+ [Description("歇业中")]
+ Stop,
+ [Description("设备维护")]
+ Repair,
+ [Description("暂停营业")]
+ Suspend,
+
+
+ }
+ ///
+ /// 换电方式:1:自动换电 2:手动换电
+ ///
+ public enum StationWay
+ {
+
+ [Description("自动换电")]
+ Auto=1,
+ [Description("手动换电")]
+ Manual,
+
+ }
+ ///
+ /// 换电模式:1:本地换电 2:远程换电
+ ///
+ public enum StationModel
+ {
+
+ [Description("本地换电")]
+ Local=1,
+ [Description("远程换电、云平台参与")]
+ Remote,
+
+ }
+
+ 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/Repository/Station/SwapOrderBatteryRepository.cs b/Repository/Station/SwapOrderBatteryRepository.cs
new file mode 100644
index 0000000..880786c
--- /dev/null
+++ b/Repository/Station/SwapOrderBatteryRepository.cs
@@ -0,0 +1,14 @@
+using Entity.DbModel.Station;
+using HybirdFrameworkCore.Autofac.Attribute;
+using SqlSugar;
+
+namespace Repository.Station;
+
+[Scope("SingleInstance")]
+public class SwapOrderBatteryRepository:BaseRepository
+{
+
+ public SwapOrderBatteryRepository(ISqlSugarClient sqlSugar) : base(sqlSugar)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Repository/Station/SwapOrderRepository.cs b/Repository/Station/SwapOrderRepository.cs
new file mode 100644
index 0000000..1d80947
--- /dev/null
+++ b/Repository/Station/SwapOrderRepository.cs
@@ -0,0 +1,14 @@
+using Entity.DbModel.Station;
+using HybirdFrameworkCore.Autofac.Attribute;
+using SqlSugar;
+
+namespace Repository.Station;
+
+[Scope("SingleInstance")]
+public class SwapOrderRepository:BaseRepository
+{
+
+ public SwapOrderRepository(ISqlSugarClient sqlSugar) : base(sqlSugar)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Repository/Station/SwapOrderStepRepository.cs b/Repository/Station/SwapOrderStepRepository.cs
new file mode 100644
index 0000000..9c03534
--- /dev/null
+++ b/Repository/Station/SwapOrderStepRepository.cs
@@ -0,0 +1,14 @@
+using Entity.DbModel.Station;
+using HybirdFrameworkCore.Autofac.Attribute;
+using SqlSugar;
+
+namespace Repository.Station;
+
+[Scope("SingleInstance")]
+public class SwapOrderStepRepository:BaseRepository
+{
+
+ public SwapOrderStepRepository(ISqlSugarClient sqlSugar) : base(sqlSugar)
+ {
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Api/CloudApi.cs b/Service/Execute/Api/CloudApi.cs
new file mode 100644
index 0000000..8745576
--- /dev/null
+++ b/Service/Execute/Api/CloudApi.cs
@@ -0,0 +1,6 @@
+namespace Service.Execute.Api;
+
+public class CloudApi
+{
+
+}
\ No newline at end of file
diff --git a/Service/Execute/Api/PlcApi.cs b/Service/Execute/Api/PlcApi.cs
new file mode 100644
index 0000000..3f5b381
--- /dev/null
+++ b/Service/Execute/Api/PlcApi.cs
@@ -0,0 +1,36 @@
+using Service.Init.Entity;
+
+namespace Service.Execute.Api;
+
+public class PlcApi
+{
+ ///
+ /// 是否远程模式
+ ///
+ ///
+ public static bool IsRemote()
+ {
+
+ return true;
+ }
+
+ ///
+ /// 入口雷达检测
+ ///
+ ///
+ public static bool EntranceRadar()
+ {
+ //TODO::
+ return true;
+ }
+
+ ///
+ /// 出口雷达检测
+ ///
+ ///
+ public static bool ExitRadar()
+ {
+ //TODO::
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Api/RfidApi.cs b/Service/Execute/Api/RfidApi.cs
new file mode 100644
index 0000000..26f0802
--- /dev/null
+++ b/Service/Execute/Api/RfidApi.cs
@@ -0,0 +1,78 @@
+using log4net;
+using Newtonsoft.Json;
+using Swapping.Business.Rfid;
+
+namespace Service.Execute.Api;
+
+public class RfidApi
+{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(RfidApi));
+ //TODO::Rfid 服务地址
+ private static readonly string BASE_URL = "http://localhost:7243";
+
+ private static readonly HttpClient _httpClient = new HttpClient()
+ {
+ Timeout = TimeSpan.FromSeconds(60)
+ };
+
+ public static async Task BeginRead()
+ {
+ Log.Info("BeginRead");
+ string url = BASE_URL + "/Api/BeginRead";
+ try
+ {
+ string s = await _httpClient.GetStringAsync(url);
+ Log.Info($"BeginRead resp = {s}");
+ return bool.Parse(s);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ return false;
+ }
+ }
+
+ public static async Task StopRead()
+ {
+ Log.Info("StopRead");
+ string url = BASE_URL + "/Api/StopRead";
+ try
+ {
+ string s = await _httpClient.GetStringAsync(url);
+ Log.Info($"StopRead resp = {s}");
+ return bool.Parse(s);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ return false;
+ }
+ }
+
+ public static async Task ReadRifd()
+ {
+ Log.Info("ReadRifd");
+ string url = BASE_URL + "/Api/ReadRfidData";
+ try
+ {
+ string s = await _httpClient.GetStringAsync(url);
+ Log.Info($"ReadRifd resp={s}");
+ if (s != String.Empty)
+ {
+ RfidReadModel? model = JsonConvert.DeserializeObject(s);
+ if (model != null)
+ {
+ return model;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ return null;
+ }
+
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/Service/Execute/Api/TboxApi.cs b/Service/Execute/Api/TboxApi.cs
new file mode 100644
index 0000000..b0817c4
--- /dev/null
+++ b/Service/Execute/Api/TboxApi.cs
@@ -0,0 +1,6 @@
+namespace Service.Execute.Api;
+
+public class TBoxApi
+{
+
+}
\ No newline at end of file
diff --git a/Service/Execute/Enum/InfoEnum.cs b/Service/Execute/Enum/InfoEnum.cs
new file mode 100644
index 0000000..c93d07c
--- /dev/null
+++ b/Service/Execute/Enum/InfoEnum.cs
@@ -0,0 +1,95 @@
+using Service.Execute.Tech;
+using Swapping.Business.Tech;
+
+namespace Service.Execute.Enum;
+
+public class InfoEnum
+{
+ public enum SwapInfo : ushort
+ {
+ [Info("Rfid读写失败", "Rfid读写失败")] ErrorReadRfid = 1,
+ [Info("车辆进站", "车辆进站")] InfoCarIn = 2,
+
+ [Info("Tbox连接失败", "Tbox连接失败,请联系站务人员")] ErrorTBoxConn = 4,
+ [Info("云端校验失败", "云端校验失败,请联系站务人员")] ErrorCloudCheck = 5,
+ [Info("车辆已到位", "车辆已到位")] InfoCarInPosition = 6,
+ [Info("车辆到位超时", "车辆到位超时")] ErrorCarInPositionTimeout = 7,
+ [Info("云平台下发换电失败", "云平台下发换电超时")] CloudSendSwapError = 8,
+
+
+ [Info("自由度调整,挂N挡,拉手刹", "自由度调整,挂N挡,拉手刹")]
+ InfoCarPrepare = 9,
+ [Info("自由度调整超时", "自由度调整超时")] ErrorCarPrepareTimeout = 10,
+ [Info("请选择更换电池数量", "请选择更换电池数量")] InfoSelectPack = 11,
+ [Info("选包失败,请驶离", "选包失败,请驶离")] ErrorSelectPack = 12,
+
+ [Info("下高压失败,请联系站务人员", "下高压失败,请联系站务人员")]
+ ErrorHvPwrOff = 13,
+
+ [Info("下低压失败,请联系站务人员", "下低压失败,请联系站务人员")]
+ ErrorLvPwrOff = 14,
+ [Info("电池拆卸中,请稍后", "电池拆卸中,请稍后")] InfoUnPack = 15,
+ [Info("电池安装中,请稍后", "电池安装中,请稍后")] InfoPack = 16,
+ [Info("电池包已安装完成", "电池包已安装完成")] InfoPackFinish = 17,
+ [Info("车辆自检中,请稍后", "车辆自检中,请稍后")] InfoSelfCheck = 18,
+ [Info("自检失败,请联系站务人员", "自检失败,请联系站务人员")] ErrorSelfCheck = 19,
+ [Info("换电已完成,请驶离", "换电已完成,请驶离")] InfoCarLeave = 20,
+ }
+
+ public enum SelectBinStatusInfo : byte
+ {
+ [Remark("通道的电池仓无换电电池")] NoBattery,
+ [Remark("可以换电")] Success,
+ [Remark("结束充电电池数量不足")] LessOfFinishCharging,
+ [Remark("空仓不够放")] LessOfEmptyBin,
+ [Remark("符合soc限制数量不足")] LessOfSoc,
+ [Remark("结束充电大于3分钟的数量不足")] LessOf3Minute,
+ [Remark("各种差数量不足")] LessOfMean,
+ [Remark("未被预约数量不足")] LessOfUnAmt,
+ [Remark("预约电池异常")] AmtError,
+ [Remark("电池捆绑选包失败")] GroupError,
+ [Remark("无可用捆绑")] NoGroupError
+ }
+
+ //1:预约成功;2:预约取消;3:预约失败;4:换电完成;5:换电失败
+ public enum AmtOrderStatus : byte
+ {
+ [Remark("预约成功")] Success = 1,
+ [Remark("预约取消")] Cancel = 2,
+ [Remark("预约失败")] Fail = 3,
+ [Remark("换电完成")] SwapFinish = 4,
+ [Remark("换电失败")] SwapFail = 5,
+ [Remark("换电中")] Swapping = 6,
+ [Remark("预约失败")] Expire = 7,
+ }
+
+ public enum BusinessSwappingState : byte
+ {
+ [Remark("未知")] UnKnown,
+ [Remark("空闲")] Idle,
+ [Remark("RFID扫描完成")] ScanRfid,
+ [Remark("云平台验证完成")] CloudCheck,
+ [Remark("车辆到位")] CarInPosition,
+ [Remark("车辆准备完成(N档、手刹)")] CarPrepare,
+ [Remark("云平台启动换电完成")] CloudBeginSwap,
+ [Remark("车辆调整完成(下高压、下低压)")] CarAdjust,
+ [Remark("开始换电")] BeginSwap,
+ [Remark("拆卸亏电包")] UnPack,
+ [Remark("安装满电包")] Pack,
+ [Remark("包安装完成")] PackFinish,
+ [Remark("车辆自检")] CarSelfCheck,
+ [Remark("换电完成(车辆驶离)")] SwapDone
+ }
+
+ public enum AmtBatLockStatus : byte
+ {
+ UnLock = 0,
+ Lock = 1
+ }
+
+ public enum SwapOrderResult : byte
+ {
+ Success = 0,
+ Fail = 1
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Enum/SwapOrderNoGenerator.cs b/Service/Execute/Enum/SwapOrderNoGenerator.cs
new file mode 100644
index 0000000..75f4f83
--- /dev/null
+++ b/Service/Execute/Enum/SwapOrderNoGenerator.cs
@@ -0,0 +1,20 @@
+namespace Swapping.Business.Common;
+
+public class SwapOrderNoGenerator
+{
+ private static UInt16 Seq = 0;
+ private static Object Locker = new object();
+
+ public static string GenerateOrderNo(string stationNo)
+ {
+ lock (Locker)
+ {
+ if (Seq > 9999)
+ {
+ Seq = 0;
+ }
+
+ return $"{stationNo}{DateTime.Now.ToString("yyyyMMddHHmmss")}{Seq++.ToString().PadLeft(6, '0')}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/IState.cs b/Service/Execute/IState.cs
new file mode 100644
index 0000000..79cade5
--- /dev/null
+++ b/Service/Execute/IState.cs
@@ -0,0 +1,9 @@
+
+
+namespace Service.Execute;
+
+public interface IState
+{
+ public StateResult? Handle(SwappingStateMachine machine);
+
+}
\ No newline at end of file
diff --git a/Service/Execute/Invoker.cs b/Service/Execute/Invoker.cs
new file mode 100644
index 0000000..c371974
--- /dev/null
+++ b/Service/Execute/Invoker.cs
@@ -0,0 +1,167 @@
+using log4net;
+
+namespace Service.Execute;
+
+public class Invoker
+{
+ private static readonly ILog Log = LogManager.GetLogger(typeof(Invoker));
+
+ public static InvokeStatus Invoke(string name, int duration, int times, Func cancel, Func done,
+ Action doAction,
+ Action timeoutAction, bool isTimeOutExit)
+ {
+ int hvPwrOffTimes = 0;
+ while (!done())
+ {
+ Log.Info($"begin {name}");
+ Thread.Sleep(duration);
+ if (cancel())
+ {
+ Log.Info($" {name} canceled");
+ return InvokeStatus.Cancel;
+ }
+
+ try
+ {
+ doAction();
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{name}", e);
+ }
+
+ 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 hvPwrOffTimes = 0;
+ while (!done())
+ {
+ Log.Info($"begin {name}");
+ Thread.Sleep(duration);
+ if (cancel())
+ {
+ Log.Info($" {name} canceled");
+ return InvokeStatus.Cancel;
+ }
+
+ try
+ {
+ doAction();
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{name}", e);
+ 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)
+ {
+ int count = 0;
+ while (!done())
+ {
+ Log.Info($"begin {name}");
+ Thread.Sleep(duration);
+ if (cancel())
+ {
+ Log.Info($" {name} canceled");
+ return InvokeStatus.Cancel;
+ }
+
+ try
+ {
+ doAction();
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{name}", e);
+ exceptionAction();
+ }
+
+ if (count++ > times)
+ {
+ if (count % timeOutActionTime == 0)
+ {
+ timeoutAction();
+ Log.Info($" {name} timeout");
+ if (isTimeOutExit)
+ {
+ return timeOutException;
+ }
+ }
+ }
+ }
+
+ Log.Info($" {name} done");
+ return InvokeStatus.Done;
+ }
+
+ public static InvokeStatus Invoke(string name, int duration, int times, Func cancel, Func done,
+ Action doAction)
+ {
+ int hvPwrOffTimes = 0;
+ while (!done())
+ {
+ Log.Info($"begin {name}");
+ Thread.Sleep(duration);
+ if (cancel())
+ {
+ Log.Info($" {name} canceled");
+ return InvokeStatus.Cancel;
+ }
+
+ try
+ {
+ doAction();
+ }
+ catch (Exception e)
+ {
+ Log.Error($"{name}", e);
+ }
+ }
+
+ Log.Info($" {name} done");
+ return InvokeStatus.Done;
+ }
+}
+
+public enum InvokeStatus
+{
+ Cancel,
+ TimeOut,
+ Done,
+ Exception
+}
\ No newline at end of file
diff --git a/Service/Execute/Model/RfidReadModel.cs b/Service/Execute/Model/RfidReadModel.cs
new file mode 100644
index 0000000..e4115f1
--- /dev/null
+++ b/Service/Execute/Model/RfidReadModel.cs
@@ -0,0 +1,31 @@
+namespace Swapping.Business.Rfid;
+
+public class RfidReadModel
+{
+ public string Result { get; set; }
+
+ ///
+ /// 车辆VIN码
+ ///
+ public string VelVin { get; set; }
+
+ ///
+ /// 车辆电池包数
+ ///
+ public string BattNum { set; get; }
+
+ ///
+ /// 车辆配方-加解锁高度,整型,单位:mm
+ ///
+ public string VelRecp { set; get; }
+
+ ///
+ /// 车辆MAC地址
+ ///
+ public string VelMac { set; get; }
+
+ ///
+ /// 车辆车牌号
+ ///
+ public string VelNo { set; get; }
+}
\ No newline at end of file
diff --git a/Service/Execute/StateResult.cs b/Service/Execute/StateResult.cs
new file mode 100644
index 0000000..c62dd53
--- /dev/null
+++ b/Service/Execute/StateResult.cs
@@ -0,0 +1,23 @@
+using Service.Execute.SwapException;
+
+namespace Service.Execute;
+
+public class StateResult
+{
+ public static readonly StateResult Cancel = new() { SwappingState = SwappingState.Canceled };
+ public SwappingState SwappingState { get; set; }
+ public Object Model { get; set; }
+
+ public static StateResult Exception(ExceptionReason exceptionReason, string msg)
+ {
+ return new StateResult()
+ {
+ SwappingState = SwappingState.Exception,
+ Model = new ExceptionData()
+ {
+ ExceptionReason = exceptionReason,
+ Msg = msg
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/StaticTools/LedReference.cs b/Service/Execute/StaticTools/LedReference.cs
new file mode 100644
index 0000000..da23dfe
--- /dev/null
+++ b/Service/Execute/StaticTools/LedReference.cs
@@ -0,0 +1,529 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+//
+// 对此文件的更改可能导致不正确的行为,并在以下条件下丢失:
+// 代码重新生成。
+//
+//------------------------------------------------------------------------------
+
+namespace ServiceReferenceLed
+{
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReferenceLed.WebServiceLedSoap")]
+ public interface WebServiceLedSoap
+ {
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/LedConnect", ReplyAction="*")]
+ System.Threading.Tasks.Task LedConnectAsync();
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/LedDisConnect", ReplyAction="*")]
+ System.Threading.Tasks.Task LedDisConnectAsync();
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/GetLedConnectedSts", ReplyAction="*")]
+ System.Threading.Tasks.Task GetLedConnectedStsAsync();
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/WriteWelcome", ReplyAction="*")]
+ System.Threading.Tasks.Task WriteWelcomeAsync(ServiceReferenceLed.WriteWelcomeRequest request);
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/WriteContent", ReplyAction="*")]
+ System.Threading.Tasks.Task WriteContentAsync(ServiceReferenceLed.WriteContentRequest request);
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/WriteProgramContent", ReplyAction="*")]
+ System.Threading.Tasks.Task WriteProgramContentAsync(ServiceReferenceLed.WriteProgramContentRequest request);
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/WriteProgramWelcome", ReplyAction="*")]
+ System.Threading.Tasks.Task WriteProgramWelcomeAsync(ServiceReferenceLed.WriteProgramWelcomeRequest request);
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/WriteClearScreen", ReplyAction="*")]
+ System.Threading.Tasks.Task WriteClearScreenAsync();
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteWelcomeRequest
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteWelcome", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteWelcomeRequestBody Body;
+
+ public WriteWelcomeRequest()
+ {
+ }
+
+ public WriteWelcomeRequest(ServiceReferenceLed.WriteWelcomeRequestBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute(Namespace="http://tempuri.org/")]
+ public partial class WriteWelcomeRequestBody
+ {
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
+ public string str_cn;
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=1)]
+ public string str_cn1;
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=2)]
+ public string str_cn2;
+
+ public WriteWelcomeRequestBody()
+ {
+ }
+
+ public WriteWelcomeRequestBody(string str_cn, string str_cn1, string str_cn2)
+ {
+ this.str_cn = str_cn;
+ this.str_cn1 = str_cn1;
+ this.str_cn2 = str_cn2;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteWelcomeResponse
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteWelcomeResponse", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteWelcomeResponseBody Body;
+
+ public WriteWelcomeResponse()
+ {
+ }
+
+ public WriteWelcomeResponse(ServiceReferenceLed.WriteWelcomeResponseBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute()]
+ public partial class WriteWelcomeResponseBody
+ {
+
+ public WriteWelcomeResponseBody()
+ {
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteContentRequest
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteContent", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteContentRequestBody Body;
+
+ public WriteContentRequest()
+ {
+ }
+
+ public WriteContentRequest(ServiceReferenceLed.WriteContentRequestBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute(Namespace="http://tempuri.org/")]
+ public partial class WriteContentRequestBody
+ {
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
+ public string content;
+
+ public WriteContentRequestBody()
+ {
+ }
+
+ public WriteContentRequestBody(string content)
+ {
+ this.content = content;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteContentResponse
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteContentResponse", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteContentResponseBody Body;
+
+ public WriteContentResponse()
+ {
+ }
+
+ public WriteContentResponse(ServiceReferenceLed.WriteContentResponseBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute()]
+ public partial class WriteContentResponseBody
+ {
+
+ public WriteContentResponseBody()
+ {
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteProgramContentRequest
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteProgramContent", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteProgramContentRequestBody Body;
+
+ public WriteProgramContentRequest()
+ {
+ }
+
+ public WriteProgramContentRequest(ServiceReferenceLed.WriteProgramContentRequestBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute(Namespace="http://tempuri.org/")]
+ public partial class WriteProgramContentRequestBody
+ {
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
+ public string content;
+
+ public WriteProgramContentRequestBody()
+ {
+ }
+
+ public WriteProgramContentRequestBody(string content)
+ {
+ this.content = content;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteProgramContentResponse
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteProgramContentResponse", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteProgramContentResponseBody Body;
+
+ public WriteProgramContentResponse()
+ {
+ }
+
+ public WriteProgramContentResponse(ServiceReferenceLed.WriteProgramContentResponseBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute()]
+ public partial class WriteProgramContentResponseBody
+ {
+
+ public WriteProgramContentResponseBody()
+ {
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteProgramWelcomeRequest
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteProgramWelcome", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteProgramWelcomeRequestBody Body;
+
+ public WriteProgramWelcomeRequest()
+ {
+ }
+
+ public WriteProgramWelcomeRequest(ServiceReferenceLed.WriteProgramWelcomeRequestBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute(Namespace="http://tempuri.org/")]
+ public partial class WriteProgramWelcomeRequestBody
+ {
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=0)]
+ public string str_cn;
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=1)]
+ public string str_cn1;
+
+ [System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false, Order=2)]
+ public string str_cn2;
+
+ public WriteProgramWelcomeRequestBody()
+ {
+ }
+
+ public WriteProgramWelcomeRequestBody(string str_cn, string str_cn1, string str_cn2)
+ {
+ this.str_cn = str_cn;
+ this.str_cn1 = str_cn1;
+ this.str_cn2 = str_cn2;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
+ public partial class WriteProgramWelcomeResponse
+ {
+
+ [System.ServiceModel.MessageBodyMemberAttribute(Name="WriteProgramWelcomeResponse", Namespace="http://tempuri.org/", Order=0)]
+ public ServiceReferenceLed.WriteProgramWelcomeResponseBody Body;
+
+ public WriteProgramWelcomeResponse()
+ {
+ }
+
+ public WriteProgramWelcomeResponse(ServiceReferenceLed.WriteProgramWelcomeResponseBody Body)
+ {
+ this.Body = Body;
+ }
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ [System.Runtime.Serialization.DataContractAttribute()]
+ public partial class WriteProgramWelcomeResponseBody
+ {
+
+ public WriteProgramWelcomeResponseBody()
+ {
+ }
+ }
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ public interface WebServiceLedSoapChannel : ServiceReferenceLed.WebServiceLedSoap, System.ServiceModel.IClientChannel
+ {
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ public partial class WebServiceLedSoapClient : System.ServiceModel.ClientBase, ServiceReferenceLed.WebServiceLedSoap
+ {
+
+ ///
+ /// 实现此分部方法,配置服务终结点。
+ ///
+ /// 要配置的终结点
+ /// 客户端凭据
+ static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
+
+ public WebServiceLedSoapClient(EndpointConfiguration endpointConfiguration) :
+ base(WebServiceLedSoapClient.GetBindingForEndpoint(endpointConfiguration), WebServiceLedSoapClient.GetEndpointAddress(endpointConfiguration))
+ {
+ this.Endpoint.Name = endpointConfiguration.ToString();
+ ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+ }
+
+ public WebServiceLedSoapClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
+ base(WebServiceLedSoapClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
+ {
+ this.Endpoint.Name = endpointConfiguration.ToString();
+ ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+ }
+
+ public WebServiceLedSoapClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(WebServiceLedSoapClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
+ {
+ this.Endpoint.Name = endpointConfiguration.ToString();
+ ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+ }
+
+ public WebServiceLedSoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(binding, remoteAddress)
+ {
+ }
+
+ public System.Threading.Tasks.Task LedConnectAsync()
+ {
+ return base.Channel.LedConnectAsync();
+ }
+
+ public System.Threading.Tasks.Task LedDisConnectAsync()
+ {
+ return base.Channel.LedDisConnectAsync();
+ }
+
+ public System.Threading.Tasks.Task GetLedConnectedStsAsync()
+ {
+ return base.Channel.GetLedConnectedStsAsync();
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ System.Threading.Tasks.Task ServiceReferenceLed.WebServiceLedSoap.WriteWelcomeAsync(ServiceReferenceLed.WriteWelcomeRequest request)
+ {
+ return base.Channel.WriteWelcomeAsync(request);
+ }
+
+ public System.Threading.Tasks.Task WriteWelcomeAsync(string str_cn, string str_cn1, string str_cn2)
+ {
+ ServiceReferenceLed.WriteWelcomeRequest inValue = new ServiceReferenceLed.WriteWelcomeRequest();
+ inValue.Body = new ServiceReferenceLed.WriteWelcomeRequestBody();
+ inValue.Body.str_cn = str_cn;
+ inValue.Body.str_cn1 = str_cn1;
+ inValue.Body.str_cn2 = str_cn2;
+ return ((ServiceReferenceLed.WebServiceLedSoap)(this)).WriteWelcomeAsync(inValue);
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ System.Threading.Tasks.Task ServiceReferenceLed.WebServiceLedSoap.WriteContentAsync(ServiceReferenceLed.WriteContentRequest request)
+ {
+ return base.Channel.WriteContentAsync(request);
+ }
+
+ public System.Threading.Tasks.Task WriteContentAsync(string content)
+ {
+ ServiceReferenceLed.WriteContentRequest inValue = new ServiceReferenceLed.WriteContentRequest();
+ inValue.Body = new ServiceReferenceLed.WriteContentRequestBody();
+ inValue.Body.content = content;
+ return ((ServiceReferenceLed.WebServiceLedSoap)(this)).WriteContentAsync(inValue);
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ System.Threading.Tasks.Task ServiceReferenceLed.WebServiceLedSoap.WriteProgramContentAsync(ServiceReferenceLed.WriteProgramContentRequest request)
+ {
+ return base.Channel.WriteProgramContentAsync(request);
+ }
+
+ public System.Threading.Tasks.Task WriteProgramContentAsync(string content)
+ {
+ ServiceReferenceLed.WriteProgramContentRequest inValue = new ServiceReferenceLed.WriteProgramContentRequest();
+ inValue.Body = new ServiceReferenceLed.WriteProgramContentRequestBody();
+ inValue.Body.content = content;
+ return ((ServiceReferenceLed.WebServiceLedSoap)(this)).WriteProgramContentAsync(inValue);
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ System.Threading.Tasks.Task ServiceReferenceLed.WebServiceLedSoap.WriteProgramWelcomeAsync(ServiceReferenceLed.WriteProgramWelcomeRequest request)
+ {
+ return base.Channel.WriteProgramWelcomeAsync(request);
+ }
+
+ public System.Threading.Tasks.Task WriteProgramWelcomeAsync(string str_cn, string str_cn1, string str_cn2)
+ {
+ ServiceReferenceLed.WriteProgramWelcomeRequest inValue = new ServiceReferenceLed.WriteProgramWelcomeRequest();
+ inValue.Body = new ServiceReferenceLed.WriteProgramWelcomeRequestBody();
+ inValue.Body.str_cn = str_cn;
+ inValue.Body.str_cn1 = str_cn1;
+ inValue.Body.str_cn2 = str_cn2;
+ return ((ServiceReferenceLed.WebServiceLedSoap)(this)).WriteProgramWelcomeAsync(inValue);
+ }
+
+ public System.Threading.Tasks.Task WriteClearScreenAsync()
+ {
+ return base.Channel.WriteClearScreenAsync();
+ }
+
+ public virtual System.Threading.Tasks.Task OpenAsync()
+ {
+ return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
+ }
+
+ public virtual System.Threading.Tasks.Task CloseAsync()
+ {
+ return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
+ }
+
+ private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
+ {
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceLedSoap))
+ {
+ System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
+ result.MaxBufferSize = int.MaxValue;
+ result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
+ result.MaxReceivedMessageSize = int.MaxValue;
+ result.AllowCookies = true;
+ return result;
+ }
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceLedSoap12))
+ {
+ System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
+ System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
+ textBindingElement.MessageVersion = System.ServiceModel.Channels.MessageVersion.CreateVersion(System.ServiceModel.EnvelopeVersion.Soap12, System.ServiceModel.Channels.AddressingVersion.None);
+ result.Elements.Add(textBindingElement);
+ System.ServiceModel.Channels.HttpTransportBindingElement httpBindingElement = new System.ServiceModel.Channels.HttpTransportBindingElement();
+ httpBindingElement.AllowCookies = true;
+ httpBindingElement.MaxBufferSize = int.MaxValue;
+ httpBindingElement.MaxReceivedMessageSize = int.MaxValue;
+ result.Elements.Add(httpBindingElement);
+ return result;
+ }
+ throw new System.InvalidOperationException(string.Format("找不到名称为“{0}”的终结点。", endpointConfiguration));
+ }
+
+ private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
+ {
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceLedSoap))
+ {
+ return new System.ServiceModel.EndpointAddress("http://127.0.0.1:8081/WebServiceLed.asmx");
+ }
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceLedSoap12))
+ {
+ return new System.ServiceModel.EndpointAddress("http://127.0.0.1:8081/WebServiceLed.asmx");
+ }
+ throw new System.InvalidOperationException(string.Format("找不到名称为“{0}”的终结点。", endpointConfiguration));
+ }
+
+ public enum EndpointConfiguration
+ {
+
+ WebServiceLedSoap,
+
+ WebServiceLedSoap12,
+ }
+ }
+}
diff --git a/Service/Execute/StaticTools/LedTool.cs b/Service/Execute/StaticTools/LedTool.cs
new file mode 100644
index 0000000..6114aa7
--- /dev/null
+++ b/Service/Execute/StaticTools/LedTool.cs
@@ -0,0 +1,159 @@
+namespace Service.Execute.StaticTools
+{
+ ///
+ /// LED管理工具
+ ///
+ public class LedTool
+ {
+ static ServiceReferenceLed.WebServiceLedSoapClient client = new ServiceReferenceLed.WebServiceLedSoapClient(ServiceReferenceLed.WebServiceLedSoapClient.EndpointConfiguration.WebServiceLedSoap);
+ ///
+ /// 通讯连接
+ ///
+ public void LedConnect()
+ {
+ try
+ { if (client != null)
+ {
+ client.LedConnectAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// 通讯断开
+ ///
+ public void LedDisConnect()
+ {
+ try
+ {
+ if (client != null)
+ {
+ client.LedDisConnectAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// LED连接状态值
+ ///
+ public bool GetLedConnectedSts()
+ {
+ bool result = false;
+ try
+ {
+ if (client != null)
+ {
+ result = client.GetLedConnectedStsAsync().Result;
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ return result;
+ }
+
+ ///
+ /// 欢迎文本指令
+ ///
+ public void WriteWelcome(string str_cn, string str_cn1, string str_cn2)
+ {
+ try
+ {
+ if (client != null)
+ {
+ client.WriteWelcomeAsync(str_cn, str_cn1, str_cn2);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+
+ ///
+ /// 欢迎文本指令
+ ///
+ public void WriteContent(string content)
+ {
+ try
+ {
+ if (client != null)
+ {
+ client.WriteContentAsync(content);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// 普通文本节目
+ ///
+ /// 接收文本内容
+ public void WriteProgramContent(string content)
+ {
+ try
+ {
+ if (client != null)
+ {
+ client.WriteProgramContentAsync(content);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// 欢迎文本节目
+ ///
+ public void WriteProgramWelcome(string str_cn, string str_cn1, string str_cn2)
+ {
+ try
+ {
+ if (client != null)
+ {
+ client.WriteProgramWelcomeAsync(str_cn, str_cn1, str_cn2);
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// 清屏
+ ///
+ public void WriteClearScreen()
+ {
+ try
+ {
+ if (client != null)
+ {
+ client.WriteClearScreenAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/StaticTools/SoundReference.cs b/Service/Execute/StaticTools/SoundReference.cs
new file mode 100644
index 0000000..28d4bb7
--- /dev/null
+++ b/Service/Execute/StaticTools/SoundReference.cs
@@ -0,0 +1,145 @@
+//------------------------------------------------------------------------------
+//
+// 此代码由工具生成。
+//
+// 对此文件的更改可能导致不正确的行为,并在以下条件下丢失:
+// 代码重新生成。
+//
+//------------------------------------------------------------------------------
+
+namespace ServiceReferenceSound
+{
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ [System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReferenceSound.WebServiceSoundSoap")]
+ public interface WebServiceSoundSoap
+ {
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/PlaySoundBySwapStep", ReplyAction="*")]
+ System.Threading.Tasks.Task PlaySoundBySwapStepAsync(ushort step);
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/PlayOneSoundFile", ReplyAction="*")]
+ System.Threading.Tasks.Task PlayOneSoundFileAsync(int soundcode);
+
+ [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/PlayLoopSoundFile", ReplyAction="*")]
+ System.Threading.Tasks.Task PlayLoopSoundFileAsync(int soundcode, int interval);
+ }
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ public interface WebServiceSoundSoapChannel : ServiceReferenceSound.WebServiceSoundSoap, System.ServiceModel.IClientChannel
+ {
+ }
+
+ [System.Diagnostics.DebuggerStepThroughAttribute()]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "2.0.3")]
+ public partial class WebServiceSoundSoapClient : System.ServiceModel.ClientBase, ServiceReferenceSound.WebServiceSoundSoap
+ {
+
+ ///
+ /// 实现此分部方法,配置服务终结点。
+ ///
+ /// 要配置的终结点
+ /// 客户端凭据
+ static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);
+
+ public WebServiceSoundSoapClient(EndpointConfiguration endpointConfiguration) :
+ base(WebServiceSoundSoapClient.GetBindingForEndpoint(endpointConfiguration), WebServiceSoundSoapClient.GetEndpointAddress(endpointConfiguration))
+ {
+ this.Endpoint.Name = endpointConfiguration.ToString();
+ ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+ }
+
+ public WebServiceSoundSoapClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
+ base(WebServiceSoundSoapClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
+ {
+ this.Endpoint.Name = endpointConfiguration.ToString();
+ ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+ }
+
+ public WebServiceSoundSoapClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(WebServiceSoundSoapClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
+ {
+ this.Endpoint.Name = endpointConfiguration.ToString();
+ ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
+ }
+
+ public WebServiceSoundSoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
+ base(binding, remoteAddress)
+ {
+ }
+
+ public System.Threading.Tasks.Task PlaySoundBySwapStepAsync(ushort step)
+ {
+ return base.Channel.PlaySoundBySwapStepAsync(step);
+ }
+
+ public System.Threading.Tasks.Task PlayOneSoundFileAsync(int soundcode)
+ {
+ return base.Channel.PlayOneSoundFileAsync(soundcode);
+ }
+
+ public System.Threading.Tasks.Task PlayLoopSoundFileAsync(int soundcode, int interval)
+ {
+ return base.Channel.PlayLoopSoundFileAsync(soundcode, interval);
+ }
+
+ public virtual System.Threading.Tasks.Task OpenAsync()
+ {
+ return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
+ }
+
+ public virtual System.Threading.Tasks.Task CloseAsync()
+ {
+ return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginClose(null, null), new System.Action(((System.ServiceModel.ICommunicationObject)(this)).EndClose));
+ }
+
+ private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
+ {
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceSoundSoap))
+ {
+ System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
+ result.MaxBufferSize = int.MaxValue;
+ result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
+ result.MaxReceivedMessageSize = int.MaxValue;
+ result.AllowCookies = true;
+ return result;
+ }
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceSoundSoap12))
+ {
+ System.ServiceModel.Channels.CustomBinding result = new System.ServiceModel.Channels.CustomBinding();
+ System.ServiceModel.Channels.TextMessageEncodingBindingElement textBindingElement = new System.ServiceModel.Channels.TextMessageEncodingBindingElement();
+ textBindingElement.MessageVersion = System.ServiceModel.Channels.MessageVersion.CreateVersion(System.ServiceModel.EnvelopeVersion.Soap12, System.ServiceModel.Channels.AddressingVersion.None);
+ result.Elements.Add(textBindingElement);
+ System.ServiceModel.Channels.HttpTransportBindingElement httpBindingElement = new System.ServiceModel.Channels.HttpTransportBindingElement();
+ httpBindingElement.AllowCookies = true;
+ httpBindingElement.MaxBufferSize = int.MaxValue;
+ httpBindingElement.MaxReceivedMessageSize = int.MaxValue;
+ result.Elements.Add(httpBindingElement);
+ return result;
+ }
+ throw new System.InvalidOperationException(string.Format("找不到名称为“{0}”的终结点。", endpointConfiguration));
+ }
+
+ private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
+ {
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceSoundSoap))
+ {
+ return new System.ServiceModel.EndpointAddress("http://127.0.0.1:8080/WebServiceSound.asmx");
+ }
+ if ((endpointConfiguration == EndpointConfiguration.WebServiceSoundSoap12))
+ {
+ return new System.ServiceModel.EndpointAddress("http://127.0.0.1:8080/WebServiceSound.asmx");
+ }
+ throw new System.InvalidOperationException(string.Format("找不到名称为“{0}”的终结点。", endpointConfiguration));
+ }
+
+ public enum EndpointConfiguration
+ {
+
+ WebServiceSoundSoap,
+
+ WebServiceSoundSoap12,
+ }
+ }
+}
diff --git a/Service/Execute/StaticTools/SoundTool.cs b/Service/Execute/StaticTools/SoundTool.cs
new file mode 100644
index 0000000..c8dbc7e
--- /dev/null
+++ b/Service/Execute/StaticTools/SoundTool.cs
@@ -0,0 +1,159 @@
+namespace Service.Execute.StaticTools
+{
+ public class SoundTool
+ {
+ private static ServiceReferenceSound.WebServiceSoundSoapClient client = new ServiceReferenceSound.WebServiceSoundSoapClient(ServiceReferenceSound.WebServiceSoundSoapClient.EndpointConfiguration.WebServiceSoundSoap);
+
+ ///
+ /// 播放通道换电步骤声音
+ ///
+ /// 步骤。10:车辆已到位;40:换电开始;50:换电进行中;60:车辆换电完成;90:停止播报
+ /// 声音播放结果
+ private static bool ChannelPlayStepSound(ushort step)
+ {
+ bool bRst = false;
+ try
+ {
+ Task result = client.PlaySoundBySwapStepAsync(step);
+ }
+ catch(Exception ex)
+ {
+ ex.ToString();
+ }
+ return bRst;
+ }
+
+ ///
+ /// 根据声音编码单次播放相关语音
+ ///
+ /// 声音文件编码。比如:50001-请将车辆行驶到指定位置
+ /// 声音播放结果
+ public static void PlayOneSound(int soundCode)
+ {
+ try
+ {
+ client.PlaySoundBySwapStepAsync((ushort)soundCode);
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// 根据声音编码循环播放相关语音
+ ///
+ /// 声音文件编码。比如:50001-请将车辆行驶到指定位置
+ /// 播放声音间隔时间-秒
+ /// 声音播放结果
+ public static void PlayLoopSound(int soundcode,int interval)
+ {
+ try
+ {
+ client.PlayLoopSoundFileAsync(soundcode,interval);
+ }
+ catch (Exception ex)
+ {
+ ex.ToString();
+ }
+ }
+
+ ///
+ /// 播放欢迎语
+ ///
+ public static void PlayWelcomeSound()
+ {
+ ChannelPlayStepSound(10);
+ }
+
+ ///
+ /// 播放车辆到位,请拉手刹、熄火
+ ///
+ public static void PlayTruskIsReached()
+ {
+ ChannelPlayStepSound(40);
+ }
+
+ ///
+ /// 播放读RFID电子标签失败
+ ///
+ public static void PlayReadeRfidFail()
+ {
+ ChannelPlayStepSound(22);
+ }
+
+ ///
+ /// 播放车辆认证成功
+ ///
+ public static void PlayTruckSignOK()
+ {
+ ChannelPlayStepSound(23);
+ }
+
+ ///
+ /// 播放车辆认证失败
+ ///
+ public static void PlayTruckSignFail()
+ {
+ ChannelPlayStepSound(24);
+ }
+
+ ///
+ /// 播放蓝牙连接失败,异常结束请驶离
+ ///
+ public static void PlayBlueToothFail()
+ {
+ ChannelPlayStepSound(32);
+ }
+
+ ///
+ /// 播放换电进行中,请勿执行任何操作
+ ///
+ public static void PlaySwapStart()
+ {
+ ChannelPlayStepSound(50);
+ }
+
+ ///
+ /// 播放电池入库搬运中
+ ///
+ public static void PlayBatteryEntry()
+ {
+ ChannelPlayStepSound(51);
+ }
+
+ ///
+ /// 播放电池出库搬运中
+ ///
+ public static void PlayBatteryDelivery()
+ {
+ ChannelPlayStepSound(52);
+ }
+
+ ///
+ /// 播放电池安装完成
+ ///
+ public static void PlayBatteryFinished()
+ {
+ ChannelPlayStepSound(53);
+ }
+
+
+ ///
+ /// 播放换电完成,车辆请驶离
+ ///
+ public static void PlaySwapFinished()
+ {
+ ChannelPlayStepSound(60);
+ }
+
+ ///
+ /// 停止语音播放
+ ///
+ public static void PlaySoundStop()
+ {
+ ChannelPlayStepSound(90);
+ }
+
+ }
+}
diff --git a/Service/Execute/StationSoftMgr.cs b/Service/Execute/StationSoftMgr.cs
new file mode 100644
index 0000000..b2319bd
--- /dev/null
+++ b/Service/Execute/StationSoftMgr.cs
@@ -0,0 +1,31 @@
+
+namespace Service.Execute
+{
+ ///
+ /// 软件管理类
+ ///
+ public class StationSoftMgr
+ {
+ public static SwappingStateMachine SwappingStateMachine = SwappingStateMachine.GetInstance();
+
+
+
+ #region 换电流程启动
+
+ ///
+ /// 换电流程启动
+ ///
+ public static void SwappingStateMachineStart()
+ {
+ SwappingStateMachine.Start();
+ }
+
+
+
+
+ #endregion 换电流程启动
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/BeginState.cs b/Service/Execute/Step/BeginState.cs
new file mode 100644
index 0000000..1ae4c84
--- /dev/null
+++ b/Service/Execute/Step/BeginState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class BeginState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/CancelState.cs b/Service/Execute/Step/CancelState.cs
new file mode 100644
index 0000000..f91e9da
--- /dev/null
+++ b/Service/Execute/Step/CancelState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class CancelState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/CarCtrlState.cs b/Service/Execute/Step/CarCtrlState.cs
new file mode 100644
index 0000000..4850a4f
--- /dev/null
+++ b/Service/Execute/Step/CarCtrlState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class CarCtrlState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/CarPrepareState.cs b/Service/Execute/Step/CarPrepareState.cs
new file mode 100644
index 0000000..4db0463
--- /dev/null
+++ b/Service/Execute/Step/CarPrepareState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class CarPrepareState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/DoSwappingState.cs b/Service/Execute/Step/DoSwappingState.cs
new file mode 100644
index 0000000..a9759b1
--- /dev/null
+++ b/Service/Execute/Step/DoSwappingState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class DoSwappingState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/ExceptionState.cs b/Service/Execute/Step/ExceptionState.cs
new file mode 100644
index 0000000..650f7fd
--- /dev/null
+++ b/Service/Execute/Step/ExceptionState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class ExceptionState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/SelectPackState.cs b/Service/Execute/Step/SelectPackState.cs
new file mode 100644
index 0000000..6469a08
--- /dev/null
+++ b/Service/Execute/Step/SelectPackState.cs
@@ -0,0 +1,14 @@
+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
new file mode 100644
index 0000000..6832ae6
--- /dev/null
+++ b/Service/Execute/Step/StationReadyState.cs
@@ -0,0 +1,219 @@
+using System.Text;
+using Entity.Constant;
+using Entity.DbModel.Station;
+using log4net;
+using Microsoft.VisualBasic;
+using Newtonsoft.Json;
+using Repository.Station;
+using Service.Execute.Api;
+using Service.Execute.Enum;
+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;
+
+public class StationReadyState : IState
+{
+ private readonly ILog _log = LogManager.GetLogger(typeof(StationReadyState));
+
+
+ public SwapOrderRepository SwapOrderRepository { get; set; }
+
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+ _log.Info($"'goto stationReady");
+
+ machine.Reset();
+ SwappingStateMachine.BusinessSwappingState = InfoEnum.BusinessSwappingState.Idle;
+ SwappingStateMachine.BusinessSwappingStateUpdateTime = DateTime.Now;
+
+ //判断换电站是否具备换电条件
+ if (!IsAutoSwapping())
+ {
+ return null;
+ }
+
+ //plc是否是远程模式
+ var plcIsRemote = PlcIsRemote(machine);
+ if (InvokeStatus.Done != plcIsRemote)
+ {
+ return SwappingStateMachine.ReturnWithInvokeErr(plcIsRemote, ExceptionReason.None);
+ }
+
+
+ //监测雷达
+ var entranceRadar = EntranceRadar(machine);
+
+ if (InvokeStatus.Done != entranceRadar)
+ {
+ return SwappingStateMachine.ReturnWithInvokeErr(entranceRadar, ExceptionReason.None);
+ }
+
+
+ //开始读rifd
+ var beginRfid = BeginRead(machine);
+ if (InvokeStatus.Done != beginRfid)
+ {
+ return SwappingStateMachine.ReturnWithInvokeErr(beginRfid, ExceptionReason.None);
+ }
+
+
+ // 读取rfid
+ var readRfid = ReadRfid(machine);
+ if (InvokeStatus.Done != readRfid)
+ {
+ return SwappingStateMachine.ReturnWithInvokeErr(readRfid, ExceptionReason.ReadRfidError);
+ }
+
+ return new StateResult()
+ {
+ SwappingState = SwappingState.CarPrepare,
+ };
+ }
+
+
+ public InvokeStatus PlcIsRemote(SwappingStateMachine machine)
+ {
+ return Invoker.Invoke("check plc remote", 1000, 5, machine.IsCanceled, PlcApi.IsRemote,
+ () =>
+ {
+ //LED显示-欢迎光临_换电站点_正在营业(三行展示)
+ string welcomeContent = "欢迎光临" + StaticStationInfo.StationName + "正在营业";
+
+ machine.LedTool?.WriteContent(welcomeContent);
+ },
+ () => { }, false);
+ }
+
+ public InvokeStatus EntranceRadar(SwappingStateMachine machine)
+ {
+ return Invoker.Invoke("wait entrance radar", 1000, 1, machine.IsCanceled,
+ () => SwappingStateMachine.RadarInFlag, () =>
+ {
+ if (!PlcApi.EntranceRadar())
+ {
+ _log.Info("entrance radar false");
+ }
+ else
+ {
+ SwappingStateMachine.ExceptionReason = ExceptionReason.None;
+ _log.Info("entrance radar true");
+ SwappingStateMachine.RadarInFlag = true;
+ }
+ });
+ }
+
+ public InvokeStatus BeginRead(SwappingStateMachine machine)
+ {
+ return Invoker.Invoke("read rfid", 1000, 20, machine.IsCanceled,
+ () => SwappingStateMachine.BeginRfidReadFlag, () =>
+ {
+ Task beginRead = RfidApi.BeginRead();
+ beginRead.Wait();
+ if (!beginRead.Result)
+ {
+ _log.Info("begin read rfid error");
+ }
+ else
+ {
+ SwappingStateMachine.ExceptionReason = ExceptionReason.None;
+ _log.Info("begin read done");
+ SwappingStateMachine.BeginRfidReadFlag = true;
+ }
+ }, () =>
+ {
+ machine.LedTool.WriteProgramContent(InfoEnum.SwapInfo.ErrorReadRfid.GetLed());
+ SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorReadRfid);
+ }, false, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ReadRfidError; });
+ }
+
+ ///
+ /// 判断换电站是否具备换电的条件
+ /// 1、换电站状态:
+ /// 2、换电站方式:
+ ///
+ ///
+ private bool IsAutoSwapping()
+ {
+ var statusDes = StationConstant.EnumExtensions.GetDescription(StaticStationInfo.StationStatus);
+ _log.Info($"换电站处于{statusDes}状态");
+ var wayDes = StationConstant.EnumExtensions.GetDescription(StaticStationInfo.StationWay);
+ _log.Info($"换电站处于{wayDes}模式");
+
+ if (StationConstant.StationStatus.Run == StaticStationInfo.StationStatus
+ && StationConstant.StationWay.Auto == StaticStationInfo.StationWay)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private InvokeStatus ReadRfid(SwappingStateMachine machine)
+ {
+ //开始读rifd
+ return Invoker.Invoke("read rfid", 1000, 20, machine.IsCanceled,
+ () => SwappingStateMachine.RfidReadFlag, () =>
+ {
+ //TODO::开始读rfid RfidService.BeginRead();
+ Task rfidReadModel = RfidApi.ReadRifd();
+ rfidReadModel.Wait();
+ if (rfidReadModel.IsCompletedSuccessfully && rfidReadModel.Result != null)
+ {
+ var resultFVelMac = rfidReadModel.Result.VelMac;
+ StringBuilder sb = new StringBuilder(16);
+ sb.Append(resultFVelMac[0]).Append(resultFVelMac[1]).Append(" ")
+ .Append(resultFVelMac[2]).Append(resultFVelMac[3]).Append(" ")
+ .Append(resultFVelMac[4]).Append(resultFVelMac[5]).Append(" ")
+ .Append(resultFVelMac[6]).Append(resultFVelMac[7]).Append(" ")
+ .Append(resultFVelMac[8]).Append(resultFVelMac[9]).Append(" ")
+ .Append(resultFVelMac[10]).Append(resultFVelMac[11]);
+ rfidReadModel.Result.VelMac = sb.ToString();
+ machine.RfidReadModel = rfidReadModel.Result;
+ _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}");
+
+ machine.SwapOrder = SaveOrder(BuildOrder(machine.RfidReadModel));
+
+ RfidApi.StopRead();
+ _log.Info("stop read rfid");
+
+ SwappingStateMachine.RfidReadFlag = true;
+ }
+ }, () =>
+ {
+ machine.LedTool.WriteProgramContent(InfoEnum.SwapInfo.ErrorReadRfid.GetLed());
+ SoundTool.PlayOneSound((int)InfoEnum.SwapInfo.ErrorReadRfid);
+ }, true, () => { SwappingStateMachine.ExceptionReason = ExceptionReason.ReadRfidError; }, 10,
+ InvokeStatus.Exception);
+ }
+
+
+ private SwapOrder BuildOrder(RfidReadModel rfidReadModel)
+ {
+ SwapOrder swapOrder = new SwapOrder()
+ {
+ Sn = SwapOrderNoGenerator.GenerateOrderNo(StaticStationInfo.StationNo),
+ VehicleVin = rfidReadModel.VelVin,
+ VehicleMac = rfidReadModel.VelMac,
+ VehicleNo = rfidReadModel.VelNo,
+ VehicleEnterTime = DateTime.Now,
+ };
+
+ return swapOrder;
+ }
+
+ private SwapOrder SaveOrder(SwapOrder swapOrder)
+ {
+ SwapOrderRepository.Insert(swapOrder);
+ return swapOrder;
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Step/SwapDoneState.cs b/Service/Execute/Step/SwapDoneState.cs
new file mode 100644
index 0000000..2a47703
--- /dev/null
+++ b/Service/Execute/Step/SwapDoneState.cs
@@ -0,0 +1,14 @@
+namespace Service.Execute.Step;
+
+public class SwapDoneState: IState
+{
+ public StateResult Handle(SwappingStateMachine machine)
+ {
+
+ return new StateResult()
+ {
+
+ SwappingState = SwappingState.StationReady
+ };
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/SwapException/ExceptionData.cs b/Service/Execute/SwapException/ExceptionData.cs
new file mode 100644
index 0000000..f51bb33
--- /dev/null
+++ b/Service/Execute/SwapException/ExceptionData.cs
@@ -0,0 +1,9 @@
+using Service.Execute.SwapException;
+
+namespace Service.Execute;
+
+public class ExceptionData
+{
+ public ExceptionReason ExceptionReason { get; set; }
+ public string? Msg { get; set; }
+}
\ No newline at end of file
diff --git a/Service/Execute/SwapException/ExceptionReason.cs b/Service/Execute/SwapException/ExceptionReason.cs
new file mode 100644
index 0000000..26d8aa2
--- /dev/null
+++ b/Service/Execute/SwapException/ExceptionReason.cs
@@ -0,0 +1,23 @@
+namespace Service.Execute.SwapException;
+
+
+ ///
+ /// 异常原因
+ ///
+ public enum ExceptionReason
+ {
+ None,
+ ReadRfidError,
+ OpenBarrierError,
+ ConnVbleError,
+ CarStateCheckError,
+ CloudCheckError,
+ CloudVbleDataError,
+ CarInPositionError,
+ CloudSendSwapError,
+ SelectPackError,
+ HvPwrOffError,
+ LvPwrOffError,
+ SelfCheckError,
+ TimeOutError
+ }
diff --git a/Service/Execute/SwappingStateMachine.cs b/Service/Execute/SwappingStateMachine.cs
new file mode 100644
index 0000000..66d365e
--- /dev/null
+++ b/Service/Execute/SwappingStateMachine.cs
@@ -0,0 +1,208 @@
+using Entity.DbModel.Station;
+using log4net;
+using Newtonsoft.Json;
+using Service.Execute.Enum;
+using Service.Execute.StaticTools;
+using Service.Execute.Step;
+using Service.Execute.SwapException;
+using Service.Execute.Tech;
+using Swapping.Business.Rfid;
+
+namespace Service.Execute;
+
+public class SwappingStateMachine : IDisposable
+{
+ private static readonly ILog _log = LogManager.GetLogger(typeof(SwappingStateMachine));
+ private static SwappingStateMachine _swappingStateMachine = new SwappingStateMachine();
+ public static bool CancelFlag { get; set; } = false;
+ public static bool StopFlag { get; set; } = false;
+
+ public LedTool LedTool = null;
+ private Thread _executeThread;
+ private Dictionary Dictionary = new Dictionary();
+
+ private StateResult _result = new StateResult() { SwappingState = SwappingState.Begin };
+ public static InfoEnum.BusinessSwappingState BusinessSwappingState = InfoEnum.BusinessSwappingState.UnKnown;
+ public static DateTime BusinessSwappingStateUpdateTime = DateTime.Now;
+ public static ExceptionReason ExceptionReason = ExceptionReason.None;
+
+
+
+ public RfidReadModel? RfidReadModel=null;
+
+ public SwapOrder? SwapOrder=null;
+
+
+ #region 小步状态
+
+ //雷达检测/车辆进入
+ public static bool RadarInFlag = false;
+ //开始读rfid
+ public static bool BeginRfidReadFlag = false;
+ //读rfid
+ public static bool RfidReadFlag = false;
+
+ //云平台车辆认证
+ public static bool CloudVelCheckFlag = false;
+
+ //Tbox连接
+ public static bool TBoxConnectionFlag = false;
+
+ //选包
+ public static bool SelectPackFlag = false;
+
+ //车辆到位
+ public static bool VehiclesInPlaceFlag = false;
+
+ //通道定位
+ public static bool ChannelPositioningFlag = false;
+
+ //下发选包
+ public static bool DistributeSelectPackFlag = false;
+
+ //云平台下发启动换电
+ public static bool CloudPackFlag = false;
+
+ //车辆解锁
+ public static bool VelUnlockFlag = false;
+
+ //开始换电
+ public static bool StartSwappingFlag = false;
+
+ //拆旧电池
+ public static bool UnOldBatteryFlag = false;
+
+ //入库旧电池
+ public static bool StorageOldBatteryFlag = false;
+
+ //搬运新电池
+ public static bool OutNewBatteryFlag = false;
+
+ //安装新电池
+ public static bool InstallNewBatteryFlag = false;
+
+ //安装完成
+ public static bool FinishNewBatteryFlag = false;
+
+ //车辆上锁
+ public static bool VelLockFlag = false;
+
+
+ //车辆离开
+ public static bool RadarOutFlag = false;
+
+ #endregion
+
+
+ private SwappingStateMachine()
+ {
+ _executeThread = new Thread(Work);
+ _executeThread.Name = "Swapping main";
+
+ Dictionary[SwappingState.Begin] = new BeginState();
+ Dictionary[SwappingState.StationReady] = new StationReadyState();
+ Dictionary[SwappingState.CarPrepare] = new CarPrepareState();
+ Dictionary[SwappingState.SelectPack] = new SelectPackState();
+ Dictionary[SwappingState.CarCtrl] = new CarCtrlState();
+ Dictionary[SwappingState.DoSwapping] = new DoSwappingState();
+ Dictionary[SwappingState.SwapDone] = new SwapDoneState();
+ Dictionary[SwappingState.Exception] = new ExceptionState();
+ Dictionary[SwappingState.Canceled] = new CancelState();
+
+ LedTool = new LedTool();
+ }
+
+ public static SwappingStateMachine GetInstance()
+ {
+ return _swappingStateMachine;
+ }
+
+
+ public static StateResult ReturnWithInvokeErr(InvokeStatus status,ExceptionReason exceptionReason)
+ {
+ if (status == InvokeStatus.Cancel)
+ {
+ return new StateResult() { SwappingState = SwappingState.Canceled };
+ }
+ else if(status==InvokeStatus.TimeOut)
+ {
+ return null;
+ }
+ else
+ {
+ return StateResult.Exception(ExceptionReason.ReadRfidError, null);
+ }
+ }
+
+ private void Work()
+ {
+ _log.Info("State machine begin work");
+ while (!StopFlag)
+ {
+ _log.Info($"handle = {_result.SwappingState} begin");
+ try
+ {
+ StateResult? result = Dictionary[_result.SwappingState].Handle(this);
+ if (result != null)
+ {
+ _result = result;
+ }
+ }
+ catch (Exception e)
+ {
+ _log.Error($"handle {_result.SwappingState} error", e);
+ }
+
+ _log.Info($"handle = {_result.SwappingState} end");
+ Thread.Sleep(500);
+ }
+
+ _log.Info("State machine canceled");
+ }
+
+ public void Stop()
+ {
+ StopFlag = true;
+ CancelFlag = true;
+ Thread.Sleep(2000);
+ }
+
+ public bool IsCanceled()
+ {
+ return CancelFlag;
+ }
+
+ public bool Start()
+ {
+ Reset();
+ _executeThread.Start();
+ _log.Info($"start machine ok");
+ return true;
+ }
+
+ public void Reset()
+ {
+ }
+
+
+ public void Dispose()
+ {
+ StopFlag = true;
+ CancelFlag = true;
+ Thread.Sleep(2000);
+ }
+}
+
+public enum SwappingState
+{
+ Begin,
+ StationReady,
+ CarPrepare,
+ SelectPack,
+ CarCtrl,
+ DoSwapping,
+ SwapDone,
+ Exception,
+ Canceled
+}
+
diff --git a/Service/Execute/Tech/InfoAttribute.cs b/Service/Execute/Tech/InfoAttribute.cs
new file mode 100644
index 0000000..7857ae5
--- /dev/null
+++ b/Service/Execute/Tech/InfoAttribute.cs
@@ -0,0 +1,60 @@
+using System.Reflection;
+
+namespace Swapping.Business.Tech;
+
+public class InfoAttribute : Attribute
+{
+ private string _Led;
+ private string _Sound;
+
+ public InfoAttribute(string led, string sound)
+ {
+ this._Led = led;
+ this._Sound = sound;
+ }
+
+ public string GetLed()
+ {
+ return this._Led;
+ }
+
+ public string GetSound()
+ {
+ return _Sound;
+ }
+}
+
+public static class InfoExtend
+{
+ public static string GetLed(this Enum value)
+ {
+ Type type = value.GetType();
+ FieldInfo? fieldInfo = type.GetField(value.ToString());
+ if (fieldInfo != null && fieldInfo.IsDefined(typeof(InfoAttribute), true))
+ {
+ Attribute? attribute = fieldInfo.GetCustomAttribute(typeof(InfoAttribute));
+ if (attribute != null)
+ {
+ return ((InfoAttribute)attribute).GetLed();
+ }
+ }
+
+ return value.ToString();
+ }
+
+ public static string GetSound(this Enum value)
+ {
+ Type type = value.GetType();
+ FieldInfo? fieldInfo = type.GetField(value.ToString());
+ if (fieldInfo != null && fieldInfo.IsDefined(typeof(InfoAttribute), true))
+ {
+ Attribute? attribute = fieldInfo.GetCustomAttribute(typeof(InfoAttribute));
+ if (attribute != null)
+ {
+ return ((InfoAttribute)attribute).GetSound();
+ }
+ }
+
+ return value.ToString();
+ }
+}
\ No newline at end of file
diff --git a/Service/Execute/Tech/RemarkAttribute.cs b/Service/Execute/Tech/RemarkAttribute.cs
new file mode 100644
index 0000000..1ec3e7c
--- /dev/null
+++ b/Service/Execute/Tech/RemarkAttribute.cs
@@ -0,0 +1,37 @@
+using System.Reflection;
+
+namespace Service.Execute.Tech;
+
+public class RemarkAttribute : Attribute
+{
+ private string _Remark;
+
+ public RemarkAttribute(string remark)
+ {
+ this._Remark = remark;
+ }
+
+ public string GetRemark()
+ {
+ return this._Remark;
+ }
+}
+
+public static class RemarkExtend
+{
+ public static string GetRemark(this global::System.Enum value)
+ {
+ Type type = value.GetType();
+ FieldInfo? fieldInfo = type.GetField(value.ToString());
+ if (fieldInfo != null && fieldInfo.IsDefined(typeof(RemarkAttribute), true))
+ {
+ Attribute? attribute = fieldInfo.GetCustomAttribute(typeof(RemarkAttribute));
+ if (attribute != null)
+ {
+ return ((RemarkAttribute)attribute).GetRemark();
+ }
+ }
+
+ return value.ToString();
+ }
+}
\ No newline at end of file
diff --git a/Service/Init/StaticStationInfo.cs b/Service/Init/StaticStationInfo.cs
new file mode 100644
index 0000000..8f52904
--- /dev/null
+++ b/Service/Init/StaticStationInfo.cs
@@ -0,0 +1,19 @@
+using Entity.Constant;
+
+namespace Service.Init;
+
+///
+/// 换电站基本信息静态数据
+///
+public class StaticStationInfo
+{
+ public static StationConstant.StationStatus StationStatus;
+
+ public static StationConstant.StationWay StationWay;
+
+ public static StationConstant.StationModel StationModel;
+
+ public static string StationName;
+
+ public static string StationNo;
+}
\ No newline at end of file
diff --git a/Service/Service.csproj b/Service/Service.csproj
index 433e1ae..136039a 100644
--- a/Service/Service.csproj
+++ b/Service/Service.csproj
@@ -15,6 +15,10 @@
+
+
+
+
diff --git a/WebStarter/Controllers/ChargeOrderController.cs b/WebStarter/Controllers/ChargeOrderController.cs
index 9045e2b..3b17641 100644
--- a/WebStarter/Controllers/ChargeOrderController.cs
+++ b/WebStarter/Controllers/ChargeOrderController.cs
@@ -50,7 +50,7 @@ public class ChargeOrderController : ControllerBase
///
///
///
- [HttpGet("Modify")]
+ [HttpPost("Modify")]
public async Task> Modify([FromBody] ModifyChargeOrderReq req)
{
diff --git a/WebStarter/Controllers/SwapOrderController.cs b/WebStarter/Controllers/SwapOrderController.cs
index add3199..5c4a51a 100644
--- a/WebStarter/Controllers/SwapOrderController.cs
+++ b/WebStarter/Controllers/SwapOrderController.cs
@@ -29,7 +29,7 @@ public class SwapOrderController : ControllerBase
///
///
///
- [HttpGet("Modify")]
+ [HttpPost("Modify")]
public async Task> Modify([FromBody] ModifySwapOrderReq req)
{
@@ -41,8 +41,8 @@ public class SwapOrderController : ControllerBase
///
/// ids 订单列表
///
- [HttpGet("DeleteByIds")]
- public async Task> DeleteByIds(List ids)
+ [HttpPost("DeleteByIds")]
+ public async Task> DeleteByIds([FromBody] List ids)
{
return Result.Success(null);
diff --git a/WebStarter/Controllers/Test/GenController.cs b/WebStarter/Controllers/Test/GenController.cs
index 4b4ad5e..cee0a5d 100644
--- a/WebStarter/Controllers/Test/GenController.cs
+++ b/WebStarter/Controllers/Test/GenController.cs
@@ -1,9 +1,8 @@
-using Entity.DbModel.Station;
using Microsoft.AspNetCore.Mvc;
using Repository.Station;
using SqlSugar;
-namespace WebStarter.Controllers;
+namespace WebStarter.Controllers.Test;
[ApiController]
[Route("[controller]")]
@@ -38,7 +37,7 @@ public class GenController : ControllerBase
Console.WriteLine("生成完毕");
}
- [HttpGet("test115")]
+ /*[HttpGet("test115")]
public void Test115()
{
_batteryGroupRepository.Insert(new List()
@@ -63,7 +62,7 @@ public class GenController : ControllerBase
Console.WriteLine("测试完毕");
- }
+ }*/
static string ToPascalCase(string input)
diff --git a/WebStarter/Controllers/Test/WeatherForecastController.cs b/WebStarter/Controllers/Test/WeatherForecastController.cs
index 35fb358..db4465a 100644
--- a/WebStarter/Controllers/Test/WeatherForecastController.cs
+++ b/WebStarter/Controllers/Test/WeatherForecastController.cs
@@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using Service.System;
-namespace WebStarter.Controllers;
+namespace WebStarter.Controllers.Test;
[ApiController]
[Route("[controller]")]
diff --git a/WebStarter/Program.cs b/WebStarter/Program.cs
index 1ccc693..08010f6 100644
--- a/WebStarter/Program.cs
+++ b/WebStarter/Program.cs
@@ -4,7 +4,6 @@ using HybirdFrameworkCore.Autofac;
using HybirdFrameworkCore.Configuration;
using HybirdFrameworkCore.Entity;
using HybirdFrameworkCore.Redis;
-using Microsoft.OpenApi.Models;
using SqlSugar;
using SqlSugar.IOC;