我正在开发一个C#Winforms应用程序,我需要确定卡车是否采用了指定的路线,并以正确的顺序通过了这些点。有效路线的示例如下:
路线1
入口门1
比例门入口侧
比例门出口侧
出口门1
路线2
入口门2
比例门入口侧
比例门出口侧
出口2
两条路线的比例门都相同,但进出门是我需要担心的。如果卡车通过门1进入并通过门1退出,则所遵循的路线是正确的。但是,如果卡车进入2号门并从1号门出口,那么我需要发送通知。
每个门都配置了硬件作为读取点。当卡车通过读取点时,将在数据库中创建带有时间戳的记录。我设置了一个计时器,以便在指定的时间间隔内检索卡车ID的有效列表。然后它检索每辆卡车在指定时间段内通过的读取点,并将其存储在列表中。我不确定的是如何将“正确路线”列表与卡车通过的读取点列表进行比较。现在我的基础是每辆卡车每天只能进行一次旅行,并且在我得到这个之后会调整额外的行程。
这是我的计时器代码
private void tmr_Tick(object sender, EventArgs e)
{
int maxTime = int.Parse(AppSettings.GetAppSetting("MaxTime"));
List<string> _assets = new List<string>();
List<ReadPoint> _assetReads = new List<ReadPoint>();
//Get the list of assets to process
DataSet ds = du.ExecuteTextCommand("SELECT DISTINCT AssetId FROM " +
"(SELECT a.TagId, a.AssetId, a.Description, rp.Comments, DateScanned " +
"FROM AssetsReads ar JOIN Assets a on ar.AssetTagID = a.AssetTagID " +
"JOIN ReadPointLocations rp on " +
"ar.ReadPointLocationsID = rp.ReadPointLocationsID) AS AssetResult " +
"ORDER BY AssetId");
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
foreach (DataRow dr in ds.Tables[0].Rows)
{
_assets.Add(dr["AssetId"].ToString());
}
}
//Loop through and process the assets
foreach (string asset in _assets)
{
ds = du.ExecuteTextCommand("SELECT a.TagId, a.AssetId, a.Description, " +
"rp.ReadPointLocationId, rp.Comments, DateScanned " +
"FROM AssetsReads ar JOIN Assets a on ar.AssetTagID = a.AssetTagID " +
"JOIN ReadPointLocations rp on " +
"ar.ReadPointLocationsID = rp.ReadPointLocationsID " +
"WHERE a.AssetID = '" + asset + "' ORDER BY DateScanned");
if (ds != null && ds.Tables[0].Rows.Count > 0)
{
_assetReads.Clear();
foreach (DataRow dr in ds.Tables[0].Rows)
{
ReadPoint ar = new ReadPoint();
ar.ReadPointLocationId = int.Parse(dr["ReadPointLocationId"].ToString());
ar.ReadpointName = dr["Comments"].ToString();
ar.DateScanned = DateTime.Parse(dr["DateScanned"].ToString());
_assetReads.Add(ar);
}
//Check to see if the asset has been seen in the last (MaxTime) minutes
if (DateTime.Parse(_assetReads[0].DateScanned.ToString()) < DateTime.Now)
{
///////////////////////
//Send notification
///////////////////////
continue;
}
//Determine the correct route to follow
Route currentRoute = null;
foreach (Route rt in _routes)
{
foreach (ReadPoint rp in rt.ReadPoints)
{
if (_assetReads[0].ReadPointLocationId == rp.ReadPointLocationId)
{
currentRoute = rt;
break;
}
}
if (currentRoute != null)
break;
}
//Check if the route was correctly followed
if (currentRoute != null)
{
//////////////////////////////
//This is where I'm stuck
//////////////////////////////
}
}
}
}
答案 0 :(得分:1)
嗯,我认为你真的在这里关闭。根据卡车通过大门的顺序,您有一个资产(卡车)经过的ReadPointLocations(大门)列表。您还有一个通过这些大门的“正确”路径列表,并且可以根据卡车首先通过哪个门来识别应该遵循的路径。剩下要做的唯一事情是在预期的读数旁边排列卡车的大门读数,并验证卡车是否经过了应有的所有大门,按顺序排列:
//Check if the route was correctly followed
if (currentRoute != null)
{
var gatesInOrder = 0;
for(var i=0; i<_assetReads.Length; i++)
{
if(_assetReads[i].ReadPointLocationId == currentRoute[gatesInOrder])
//gate crossed in order; increment to next gate
gatesInOrder++;
}
//if we didn't get to the end of the route, send a notification
if(gatesInOrder != currentRoute.Length)
{
///////////////////////
//Send notification
///////////////////////
}
}
现在,这假设有两件事。首先,所有读取都没有错误地执行。我可以从经验告诉你,即使在自动化系统中,也会以非常高的频率错过位置扫描。这意味着如果错过了您的入口门扫描,您将无法确定卡车应该通过哪个门;您将根据您的第一次读取(即刻度入口门)选择一条路线(可能是1号门),但由于该节点对于Gate 1和Gate 2路径都是通用的,因此您将错误地通知卡车如果卡车从2号门出来,即使它通过2号门进入,也会通过错误的大门离开。为了避免这种情况,您必须能够识别每条路线中该路线独有的大门(在这种情况下) ,进入和退出门)并根据其中一个位置的第一次门扫描确定使用的正确路线,而不仅仅是任何位置。你现在已经选择了正确的路线,但是你找不到入口门扫描;你可以检测到这一点并发送一个不同的“门扫错过”通知。
其次,我们假设一旦卡车进入一条路线,它必须继续通过该路径,并且不能在任何时候偏离。没有什么可以无序完成。因此,在一个更复杂的例子中,假设卡车也经过了简单的检查(尾灯工作,没有明显的泄漏,轮胎踏板正常,怠速时无滚滚烟雾等)。如果检查和称重可以按任何顺序进行,如果称重和检查的顺序与预期相反,则会错误地发送带有上述算法的通知。你可以通过简单地检查所有正确路径的位置是否在某个时刻被扫描来避免这种天真,但是这不会捕获,例如,卡车在整个过程中走错了路。如果可能,那么您将需要更复杂的东西,例如带有条件路径的整体路线图(您可以从任一入口门进入称重或检查门,如果没有称重,则可以从检查出口进行您必须前往称重输入,反之亦然,如果您经过两个子路径,则必须在通过入口1进入1号出口,或者如果您通过入口2进入则退出2。