inital
This commit is contained in:
105
OCPP.Core.Management/Controllers/AccountController.cs
Normal file
105
OCPP.Core.Management/Controllers/AccountController.cs
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
public class AccountController : BaseController
|
||||
{
|
||||
public AccountController(
|
||||
UserManager userManager,
|
||||
ILoggerFactory loggerFactory,
|
||||
IConfiguration config,
|
||||
OCPPCoreContext dbContext) : base(userManager, loggerFactory, config, dbContext)
|
||||
{
|
||||
Logger = loggerFactory.CreateLogger<AccountController>();
|
||||
}
|
||||
|
||||
// GET: /Account/Login
|
||||
[HttpGet]
|
||||
[AllowAnonymous]
|
||||
public IActionResult Login(string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
return View();
|
||||
}
|
||||
|
||||
// POST: /Account/Login
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Login(UserModel userModel, string returnUrl = null)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
await UserManager.SignIn(this.HttpContext, userModel, false);
|
||||
if (userModel != null && !string.IsNullOrWhiteSpace(userModel.Username))
|
||||
{
|
||||
Logger.LogInformation("User '{0}' logged in", userModel.Username);
|
||||
return RedirectToLocal(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation("Invalid login attempt: User '{0}'", userModel.Username);
|
||||
ModelState.AddModelError(string.Empty, "Invalid login attempt");
|
||||
return View(userModel);
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(userModel);
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> Logout(UserModel userModel)
|
||||
{
|
||||
Logger.LogInformation("Signing our user '{0}'", userModel.Username);
|
||||
await UserManager.SignOut(this.HttpContext);
|
||||
|
||||
return RedirectToAction(nameof(AccountController.Login), "Account");
|
||||
}
|
||||
|
||||
private IActionResult RedirectToLocal(string returnUrl)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl))
|
||||
{
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
return RedirectToAction(nameof(HomeController.Index), Constants.HomeController);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
177
OCPP.Core.Management/Controllers/ApiController.Reset.cs
Normal file
177
OCPP.Core.Management/Controllers/ApiController.Reset.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using OCPP.Core.Database;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class ApiController : BaseController
|
||||
{
|
||||
private readonly IStringLocalizer<ApiController> _localizer;
|
||||
|
||||
public ApiController(
|
||||
UserManager userManager,
|
||||
IStringLocalizer<ApiController> localizer,
|
||||
ILoggerFactory loggerFactory,
|
||||
IConfiguration config,
|
||||
OCPPCoreContext dbContext) : base(userManager, loggerFactory, config, dbContext)
|
||||
{
|
||||
_localizer = localizer;
|
||||
Logger = loggerFactory.CreateLogger<ApiController>();
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public async Task<IActionResult> Reset(string Id)
|
||||
{
|
||||
if (User != null && !User.IsInRole(Constants.AdminRoleName))
|
||||
{
|
||||
Logger.LogWarning("Reset: Request by non-administrator: {0}", User?.Identity?.Name);
|
||||
return StatusCode((int)HttpStatusCode.Unauthorized);
|
||||
}
|
||||
|
||||
int httpStatuscode = (int)HttpStatusCode.OK;
|
||||
string resultContent = string.Empty;
|
||||
|
||||
Logger.LogTrace("Reset: Request to restart chargepoint '{0}'", Id);
|
||||
if (!string.IsNullOrEmpty(Id))
|
||||
{
|
||||
try
|
||||
{
|
||||
ChargePoint chargePoint = DbContext.ChargePoints.Find(Id);
|
||||
if (chargePoint != null)
|
||||
{
|
||||
string serverApiUrl = base.Config.GetValue<string>("ServerApiUrl");
|
||||
string apiKeyConfig = base.Config.GetValue<string>("ApiKey");
|
||||
if (!string.IsNullOrEmpty(serverApiUrl))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
if (!serverApiUrl.EndsWith('/'))
|
||||
{
|
||||
serverApiUrl += "/";
|
||||
}
|
||||
Uri uri = new Uri(serverApiUrl);
|
||||
uri = new Uri(uri, $"Reset/{Uri.EscapeDataString(Id)}");
|
||||
httpClient.Timeout = new TimeSpan(0, 0, 4); // use short timeout
|
||||
|
||||
// API-Key authentication?
|
||||
if (!string.IsNullOrWhiteSpace(apiKeyConfig))
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKeyConfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Reset: No API-Key configured!");
|
||||
}
|
||||
|
||||
HttpResponseMessage response = await httpClient.GetAsync(uri);
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
string jsonResult = await response.Content.ReadAsStringAsync();
|
||||
if (!string.IsNullOrEmpty(jsonResult))
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic jsonObject = JsonConvert.DeserializeObject(jsonResult);
|
||||
Logger.LogInformation("Reset: Result of API request is '{0}'", jsonResult);
|
||||
string status = jsonObject.status;
|
||||
switch (status)
|
||||
{
|
||||
case "Accepted":
|
||||
resultContent = _localizer["ResetAccepted"];
|
||||
break;
|
||||
case "Rejected":
|
||||
resultContent = _localizer["ResetRejected"];
|
||||
break;
|
||||
case "Scheduled":
|
||||
resultContent = _localizer["ResetScheduled"];
|
||||
break;
|
||||
default:
|
||||
resultContent = string.Format(_localizer["ResetUnknownStatus"], status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Reset: Error in JSON result => {0}", exp.Message);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["ResetError"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("Reset: Result of API request is empty");
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["ResetError"];
|
||||
}
|
||||
}
|
||||
else if (response.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
// Chargepoint offline
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["ResetOffline"];
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("Reset: Result of API request => httpStatus={0}", response.StatusCode);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["ResetError"];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Reset: Error in API request => {0}", exp.Message);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["ResetError"];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Reset: Error loading charge point '{0}' from database", Id);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnknownChargepoint"];
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Reset: Error loading charge point from database");
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["ResetError"];
|
||||
}
|
||||
}
|
||||
|
||||
return StatusCode(httpStatuscode, resultContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using OCPP.Core.Database;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class ApiController : BaseController
|
||||
{
|
||||
[Authorize]
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public async Task<IActionResult> UnlockConnector(string Id)
|
||||
{
|
||||
if (User != null && !User.IsInRole(Constants.AdminRoleName))
|
||||
{
|
||||
Logger.LogWarning("UnlockConnector: Request by non-administrator: {0}", User?.Identity?.Name);
|
||||
return StatusCode((int)HttpStatusCode.Unauthorized);
|
||||
}
|
||||
|
||||
int httpStatuscode = (int)HttpStatusCode.OK;
|
||||
string resultContent = string.Empty;
|
||||
|
||||
Logger.LogTrace("UnlockConnector: Request to unlock chargepoint '{0}'", Id);
|
||||
if (!string.IsNullOrEmpty(Id))
|
||||
{
|
||||
try
|
||||
{
|
||||
ChargePoint chargePoint = DbContext.ChargePoints.Find(Id);
|
||||
if (chargePoint != null)
|
||||
{
|
||||
string serverApiUrl = base.Config.GetValue<string>("ServerApiUrl");
|
||||
string apiKeyConfig = base.Config.GetValue<string>("ApiKey");
|
||||
if (!string.IsNullOrEmpty(serverApiUrl))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
if (!serverApiUrl.EndsWith('/'))
|
||||
{
|
||||
serverApiUrl += "/";
|
||||
}
|
||||
Uri uri = new Uri(serverApiUrl);
|
||||
uri = new Uri(uri, $"UnlockConnector/{Uri.EscapeDataString(Id)}");
|
||||
httpClient.Timeout = new TimeSpan(0, 0, 4); // use short timeout
|
||||
|
||||
// API-Key authentication?
|
||||
if (!string.IsNullOrWhiteSpace(apiKeyConfig))
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKeyConfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("UnlockConnector: No API-Key configured!");
|
||||
}
|
||||
|
||||
HttpResponseMessage response = await httpClient.GetAsync(uri);
|
||||
if (response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
string jsonResult = await response.Content.ReadAsStringAsync();
|
||||
if (!string.IsNullOrEmpty(jsonResult))
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic jsonObject = JsonConvert.DeserializeObject(jsonResult);
|
||||
Logger.LogInformation("UnlockConnector: Result of API request is '{0}'", jsonResult);
|
||||
string status = jsonObject.status;
|
||||
switch (status)
|
||||
{
|
||||
case "Unlocked":
|
||||
resultContent = _localizer["UnlockConnectorAccepted"];
|
||||
break;
|
||||
case "UnlockFailed":
|
||||
case "OngoingAuthorizedTransaction":
|
||||
case "UnknownConnector":
|
||||
resultContent = _localizer["UnlockConnectorFailed"];
|
||||
break;
|
||||
case "NotSupported":
|
||||
resultContent = _localizer["UnlockConnectorNotSupported"];
|
||||
break;
|
||||
default:
|
||||
resultContent = string.Format(_localizer["UnlockConnectorUnknownStatus"], status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "UnlockConnector: Error in JSON result => {0}", exp.Message);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnlockConnectorError"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("UnlockConnector: Result of API request is empty");
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnlockConnectorError"];
|
||||
}
|
||||
}
|
||||
else if (response.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
// Chargepoint offline
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnlockConnectorOffline"];
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("UnlockConnector: Result of API request => httpStatus={0}", response.StatusCode);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnlockConnectorError"];
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "UnlockConnector: Error in API request => {0}", exp.Message);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnlockConnectorError"];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("UnlockConnector: Error loading charge point '{0}' from database", Id);
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnknownChargepoint"];
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "UnlockConnector: Error loading charge point from database");
|
||||
httpStatuscode = (int)HttpStatusCode.OK;
|
||||
resultContent = _localizer["UnlockConnectorError"];
|
||||
}
|
||||
}
|
||||
|
||||
return StatusCode(httpStatuscode, resultContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
OCPP.Core.Management/Controllers/BaseController.cs
Normal file
52
OCPP.Core.Management/Controllers/BaseController.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public class BaseController : Controller
|
||||
{
|
||||
protected UserManager UserManager { get; private set; }
|
||||
|
||||
protected ILogger Logger { get; set; }
|
||||
|
||||
protected IConfiguration Config { get; private set; }
|
||||
|
||||
protected OCPPCoreContext DbContext { get; private set; }
|
||||
|
||||
public BaseController(
|
||||
UserManager userManager,
|
||||
ILoggerFactory loggerFactory,
|
||||
IConfiguration config,
|
||||
OCPPCoreContext dbContext)
|
||||
{
|
||||
UserManager = userManager;
|
||||
Config = config;
|
||||
DbContext = dbContext;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
162
OCPP.Core.Management/Controllers/HomeController.ChargePoint.cs
Normal file
162
OCPP.Core.Management/Controllers/HomeController.ChargePoint.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class HomeController : BaseController
|
||||
{
|
||||
[Authorize]
|
||||
public IActionResult ChargePoint(string Id, ChargePointViewModel cpvm)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (User != null && !User.IsInRole(Constants.AdminRoleName))
|
||||
{
|
||||
Logger.LogWarning("ChargePoint: Request by non-administrator: {0}", User?.Identity?.Name);
|
||||
TempData["ErrMsgKey"] = "AccessDenied";
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
|
||||
cpvm.CurrentId = Id;
|
||||
|
||||
Logger.LogTrace("ChargePoint: Loading charge points...");
|
||||
List<ChargePoint> dbChargePoints = DbContext.ChargePoints.ToList<ChargePoint>();
|
||||
Logger.LogInformation("ChargePoint: Found {0} charge points", dbChargePoints.Count);
|
||||
|
||||
ChargePoint currentChargePoint = null;
|
||||
if (!string.IsNullOrEmpty(Id))
|
||||
{
|
||||
foreach (ChargePoint cp in dbChargePoints)
|
||||
{
|
||||
if (cp.ChargePointId.Equals(Id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
currentChargePoint = cp;
|
||||
Logger.LogTrace("ChargePoint: Current charge point: {0} / {1}", cp.ChargePointId, cp.Name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Request.Method == "POST")
|
||||
{
|
||||
string errorMsg = null;
|
||||
|
||||
if (Id == "@")
|
||||
{
|
||||
Logger.LogTrace("ChargePoint: Creating new charge point...");
|
||||
|
||||
// Create new tag
|
||||
if (string.IsNullOrWhiteSpace(cpvm.ChargePointId))
|
||||
{
|
||||
errorMsg = _localizer["ChargePointIdRequired"].Value;
|
||||
Logger.LogInformation("ChargePoint: New => no charge point ID entered");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(errorMsg))
|
||||
{
|
||||
// check if duplicate
|
||||
foreach (ChargePoint cp in dbChargePoints)
|
||||
{
|
||||
if (cp.ChargePointId.Equals(cpvm.ChargePointId, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
// id already exists
|
||||
errorMsg = _localizer["ChargePointIdExists"].Value;
|
||||
Logger.LogInformation("ChargePoint: New => charge point ID already exists: {0}", cpvm.ChargePointId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(errorMsg))
|
||||
{
|
||||
// Save tag in DB
|
||||
ChargePoint newChargePoint = new ChargePoint();
|
||||
newChargePoint.ChargePointId = cpvm.ChargePointId;
|
||||
newChargePoint.Name = cpvm.Name;
|
||||
newChargePoint.Comment = cpvm.Comment;
|
||||
newChargePoint.Username = cpvm.Username;
|
||||
newChargePoint.Password = cpvm.Password;
|
||||
newChargePoint.ClientCertThumb = cpvm.ClientCertThumb;
|
||||
DbContext.ChargePoints.Add(newChargePoint);
|
||||
DbContext.SaveChanges();
|
||||
Logger.LogInformation("ChargePoint: New => charge point saved: {0} / {1}", cpvm.ChargePointId, cpvm.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewBag.ErrorMsg = errorMsg;
|
||||
return View("ChargePointDetail", cpvm);
|
||||
}
|
||||
}
|
||||
else if (currentChargePoint.ChargePointId == Id)
|
||||
{
|
||||
// Save existing charge point
|
||||
Logger.LogTrace("ChargePoint: Saving charge point '{0}'", Id);
|
||||
currentChargePoint.Name = cpvm.Name;
|
||||
currentChargePoint.Comment = cpvm.Comment;
|
||||
currentChargePoint.Username = cpvm.Username;
|
||||
currentChargePoint.Password = cpvm.Password;
|
||||
currentChargePoint.ClientCertThumb = cpvm.ClientCertThumb;
|
||||
|
||||
DbContext.SaveChanges();
|
||||
Logger.LogInformation("ChargePoint: Edit => charge point saved: {0} / {1}", cpvm.ChargePointId, cpvm.Name);
|
||||
}
|
||||
|
||||
return RedirectToAction("ChargePoint", new { Id = "" });
|
||||
}
|
||||
else
|
||||
{
|
||||
// Display charge point
|
||||
cpvm = new ChargePointViewModel();
|
||||
cpvm.ChargePoints = dbChargePoints;
|
||||
cpvm.CurrentId = Id;
|
||||
|
||||
if (currentChargePoint!= null)
|
||||
{
|
||||
cpvm = new ChargePointViewModel();
|
||||
cpvm.ChargePointId = currentChargePoint.ChargePointId;
|
||||
cpvm.Name = currentChargePoint.Name;
|
||||
cpvm.Comment = currentChargePoint.Comment;
|
||||
cpvm.Username = currentChargePoint.Username;
|
||||
cpvm.Password = currentChargePoint.Password;
|
||||
cpvm.ClientCertThumb = currentChargePoint.ClientCertThumb;
|
||||
}
|
||||
|
||||
string viewName = (!string.IsNullOrEmpty(cpvm.ChargePointId) || Id == "@") ? "ChargePointDetail" : "ChargePointList";
|
||||
return View(viewName, cpvm);
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "ChargePoint: Error loading charge points from database");
|
||||
TempData["ErrMessage"] = exp.Message;
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
163
OCPP.Core.Management/Controllers/HomeController.ChargeTag.cs
Normal file
163
OCPP.Core.Management/Controllers/HomeController.ChargeTag.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class HomeController : BaseController
|
||||
{
|
||||
[Authorize]
|
||||
public IActionResult ChargeTag(string Id, ChargeTagViewModel ctvm)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (User != null && !User.IsInRole(Constants.AdminRoleName))
|
||||
{
|
||||
Logger.LogWarning("ChargeTag: Request by non-administrator: {0}", User?.Identity?.Name);
|
||||
TempData["ErrMsgKey"] = "AccessDenied";
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
|
||||
ViewBag.DatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
|
||||
ViewBag.Language = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
|
||||
ctvm.CurrentTagId = Id;
|
||||
|
||||
Logger.LogTrace("ChargeTag: Loading charge tags...");
|
||||
List<ChargeTag> dbChargeTags = DbContext.ChargeTags.ToList<ChargeTag>();
|
||||
Logger.LogInformation("ChargeTag: Found {0} charge tags", dbChargeTags.Count);
|
||||
|
||||
ChargeTag currentChargeTag = null;
|
||||
if (!string.IsNullOrEmpty(Id))
|
||||
{
|
||||
foreach (ChargeTag tag in dbChargeTags)
|
||||
{
|
||||
if (tag.TagId.Equals(Id, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
currentChargeTag = tag;
|
||||
Logger.LogTrace("ChargeTag: Current charge tag: {0} / {1}", tag.TagId, tag.TagName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Request.Method == "POST")
|
||||
{
|
||||
string errorMsg = null;
|
||||
|
||||
if (Id == "@")
|
||||
{
|
||||
Logger.LogTrace("ChargeTag: Creating new charge tag...");
|
||||
|
||||
// Create new tag
|
||||
if (string.IsNullOrWhiteSpace(ctvm.TagId))
|
||||
{
|
||||
errorMsg = _localizer["ChargeTagIdRequired"].Value;
|
||||
Logger.LogInformation("ChargeTag: New => no charge tag ID entered");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(errorMsg))
|
||||
{
|
||||
// check if duplicate
|
||||
foreach (ChargeTag tag in dbChargeTags)
|
||||
{
|
||||
if (tag.TagId.Equals(ctvm.TagId, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
// tag-id already exists
|
||||
errorMsg = _localizer["ChargeTagIdExists"].Value;
|
||||
Logger.LogInformation("ChargeTag: New => charge tag ID already exists: {0}", ctvm.TagId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(errorMsg))
|
||||
{
|
||||
// Save tag in DB
|
||||
ChargeTag newTag = new ChargeTag();
|
||||
newTag.TagId = ctvm.TagId;
|
||||
newTag.TagName = ctvm.TagName;
|
||||
newTag.ParentTagId = ctvm.ParentTagId;
|
||||
newTag.ExpiryDate = ctvm.ExpiryDate;
|
||||
newTag.Blocked = ctvm.Blocked;
|
||||
DbContext.ChargeTags.Add(newTag);
|
||||
DbContext.SaveChanges();
|
||||
Logger.LogInformation("ChargeTag: New => charge tag saved: {0} / {1}", ctvm.TagId, ctvm.TagName);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewBag.ErrorMsg = errorMsg;
|
||||
return View("ChargeTagDetail", ctvm);
|
||||
}
|
||||
}
|
||||
else if (currentChargeTag.TagId == Id)
|
||||
{
|
||||
// Save existing tag
|
||||
currentChargeTag.TagName = ctvm.TagName;
|
||||
currentChargeTag.ParentTagId = ctvm.ParentTagId;
|
||||
currentChargeTag.ExpiryDate = ctvm.ExpiryDate;
|
||||
currentChargeTag.Blocked = ctvm.Blocked;
|
||||
DbContext.SaveChanges();
|
||||
Logger.LogInformation("ChargeTag: Edit => charge tag saved: {0} / {1}", ctvm.TagId, ctvm.TagName);
|
||||
}
|
||||
|
||||
return RedirectToAction("ChargeTag", new { Id = "" });
|
||||
}
|
||||
else
|
||||
{
|
||||
// List all charge tags
|
||||
ctvm = new ChargeTagViewModel();
|
||||
ctvm.ChargeTags = dbChargeTags;
|
||||
ctvm.CurrentTagId = Id;
|
||||
|
||||
if (currentChargeTag != null)
|
||||
{
|
||||
ctvm.TagId = currentChargeTag.TagId;
|
||||
ctvm.TagName = currentChargeTag.TagName;
|
||||
ctvm.ParentTagId = currentChargeTag.ParentTagId;
|
||||
ctvm.ExpiryDate = currentChargeTag.ExpiryDate;
|
||||
ctvm.Blocked = (currentChargeTag.Blocked != null) && currentChargeTag.Blocked.Value;
|
||||
}
|
||||
|
||||
string viewName = (!string.IsNullOrEmpty(ctvm.TagId) || Id=="@") ? "ChargeTagDetail" : "ChargeTagList";
|
||||
return View(viewName, ctvm);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "ChargeTag: Error loading charge tags from database");
|
||||
TempData["ErrMessage"] = exp.Message;
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
113
OCPP.Core.Management/Controllers/HomeController.Conector.cs
Normal file
113
OCPP.Core.Management/Controllers/HomeController.Conector.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class HomeController : BaseController
|
||||
{
|
||||
[Authorize]
|
||||
public IActionResult Connector(string Id, string ConnectorId, ConnectorStatusViewModel csvm)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (User != null && !User.IsInRole(Constants.AdminRoleName))
|
||||
{
|
||||
Logger.LogWarning("Connector: Request by non-administrator: {0}", User?.Identity?.Name);
|
||||
TempData["ErrMsgKey"] = "AccessDenied";
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
|
||||
ViewBag.DatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
|
||||
ViewBag.Language = CultureInfo.CurrentCulture.TwoLetterISOLanguageName;
|
||||
|
||||
Logger.LogTrace("Connector: Loading connectors...");
|
||||
List<ConnectorStatus> dbConnectorStatuses = DbContext.ConnectorStatuses.ToList<ConnectorStatus>();
|
||||
Logger.LogInformation("Connector: Found {0} connectors", dbConnectorStatuses.Count);
|
||||
|
||||
ConnectorStatus currentConnectorStatus = null;
|
||||
if (!string.IsNullOrEmpty(Id) && !string.IsNullOrEmpty(ConnectorId))
|
||||
{
|
||||
foreach (ConnectorStatus cs in dbConnectorStatuses)
|
||||
{
|
||||
if (cs.ChargePointId.Equals(Id, StringComparison.InvariantCultureIgnoreCase) &&
|
||||
cs.ConnectorId.ToString().Equals(ConnectorId, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
currentConnectorStatus = cs;
|
||||
Logger.LogTrace("Connector: Current connector: {0} / {1}", cs.ChargePointId, cs.ConnectorId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Request.Method == "POST")
|
||||
{
|
||||
if (currentConnectorStatus.ChargePointId == Id)
|
||||
{
|
||||
// Save connector
|
||||
currentConnectorStatus.ConnectorName = csvm.ConnectorName;
|
||||
DbContext.SaveChanges();
|
||||
Logger.LogInformation("Connector: Edit => Connector saved: {0} / {1} => '{2}'", csvm.ChargePointId, csvm.ConnectorId, csvm.ConnectorName);
|
||||
}
|
||||
|
||||
return RedirectToAction("Connector", new { Id = "" });
|
||||
}
|
||||
else
|
||||
{
|
||||
// List all charge tags
|
||||
csvm = new ConnectorStatusViewModel();
|
||||
csvm.ConnectorStatuses = dbConnectorStatuses;
|
||||
|
||||
if (currentConnectorStatus != null)
|
||||
{
|
||||
csvm.ChargePointId = currentConnectorStatus.ChargePointId;
|
||||
csvm.ConnectorId = currentConnectorStatus.ConnectorId;
|
||||
csvm.ConnectorName = currentConnectorStatus.ConnectorName;
|
||||
csvm.LastStatus = currentConnectorStatus.LastStatus;
|
||||
csvm.LastStatusTime = currentConnectorStatus.LastStatusTime;
|
||||
csvm.LastMeter = currentConnectorStatus.LastMeter;
|
||||
csvm.LastMeterTime = currentConnectorStatus.LastMeterTime;
|
||||
}
|
||||
|
||||
string viewName = (currentConnectorStatus != null) ? "ConnectorDetail" : "ConnectorList";
|
||||
return View(viewName, csvm);
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Connector: Error loading connectors from database");
|
||||
TempData["ErrMessage"] = exp.Message;
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
234
OCPP.Core.Management/Controllers/HomeController.Export.cs
Normal file
234
OCPP.Core.Management/Controllers/HomeController.Export.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class HomeController : BaseController
|
||||
{
|
||||
const char CSV_Seperator = ';';
|
||||
|
||||
[Authorize]
|
||||
public IActionResult Export(string Id, string ConnectorId)
|
||||
{
|
||||
Logger.LogTrace("Export: Loading charge point transactions...");
|
||||
|
||||
int currentConnectorId = -1;
|
||||
int.TryParse(ConnectorId, out currentConnectorId);
|
||||
|
||||
TransactionListViewModel tlvm = new TransactionListViewModel();
|
||||
tlvm.CurrentChargePointId = Id;
|
||||
tlvm.CurrentConnectorId = currentConnectorId;
|
||||
tlvm.ConnectorStatuses = new List<ConnectorStatus>();
|
||||
tlvm.Transactions = new List<Transaction>();
|
||||
|
||||
try
|
||||
{
|
||||
string ts = Request.Query["t"];
|
||||
int days = 30;
|
||||
if (ts == "2")
|
||||
{
|
||||
// 90 days
|
||||
days = 90;
|
||||
tlvm.Timespan = 2;
|
||||
}
|
||||
else if (ts == "3")
|
||||
{
|
||||
// 365 days
|
||||
days = 365;
|
||||
tlvm.Timespan = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 30 days
|
||||
days = 30;
|
||||
tlvm.Timespan = 1;
|
||||
}
|
||||
|
||||
string currentConnectorName = string.Empty;
|
||||
|
||||
Logger.LogTrace("Export: Loading charge points...");
|
||||
tlvm.ConnectorStatuses = DbContext.ConnectorStatuses.ToList<ConnectorStatus>();
|
||||
|
||||
// Preferred: use specific connector name
|
||||
foreach (ConnectorStatus cs in tlvm.ConnectorStatuses)
|
||||
{
|
||||
if (cs.ChargePointId == Id && cs.ConnectorId == currentConnectorId)
|
||||
{
|
||||
currentConnectorName = cs.ConnectorName;
|
||||
/*
|
||||
if (string.IsNullOrEmpty(tlvm.CurrentConnectorName))
|
||||
{
|
||||
currentConnectorName = $"{Id}:{cs.ConnectorId}";
|
||||
}
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
// default: combined name with charge point and connector
|
||||
if (string.IsNullOrEmpty(currentConnectorName))
|
||||
{
|
||||
tlvm.ChargePoints = DbContext.ChargePoints.ToList<ChargePoint>();
|
||||
foreach(ChargePoint cp in tlvm.ChargePoints)
|
||||
{
|
||||
if (cp.ChargePointId == Id)
|
||||
{
|
||||
currentConnectorName = $"{cp.Name}:{currentConnectorId}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (string.IsNullOrEmpty(currentConnectorName))
|
||||
{
|
||||
// Fallback: ID + connector
|
||||
currentConnectorName = $"{Id}:{currentConnectorId}";
|
||||
}
|
||||
}
|
||||
|
||||
// load charge tags for name resolution
|
||||
Logger.LogTrace("Export: Loading charge tags...");
|
||||
List<ChargeTag> chargeTags = DbContext.ChargeTags.ToList<ChargeTag>();
|
||||
tlvm.ChargeTags = new Dictionary<string, ChargeTag>();
|
||||
if (chargeTags != null)
|
||||
{
|
||||
foreach (ChargeTag tag in chargeTags)
|
||||
{
|
||||
tlvm.ChargeTags.Add(tag.TagId, tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(tlvm.CurrentChargePointId))
|
||||
{
|
||||
Logger.LogTrace("Export: Loading charge point transactions...");
|
||||
tlvm.Transactions = DbContext.Transactions
|
||||
.Where(t => t.ChargePointId == tlvm.CurrentChargePointId &&
|
||||
t.ConnectorId == tlvm.CurrentConnectorId &&
|
||||
t.StartTime >= DateTime.UtcNow.AddDays(-1 * days))
|
||||
.OrderByDescending(t => t.TransactionId)
|
||||
.ToList<Transaction>();
|
||||
}
|
||||
|
||||
StringBuilder connectorName = new StringBuilder(currentConnectorName);
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
connectorName.Replace(c, '_');
|
||||
}
|
||||
|
||||
string filename = string.Format("Transactions_{0}.csv", connectorName);
|
||||
string csv = CreateCsv(tlvm, currentConnectorName);
|
||||
Logger.LogInformation("Export: File => {0} Chars / Name '{1}'", csv.Length, filename);
|
||||
|
||||
return File(Encoding.GetEncoding("ISO-8859-1").GetBytes(csv), "text/csv", filename);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Export: Error loading data from database");
|
||||
}
|
||||
|
||||
return View(tlvm);
|
||||
}
|
||||
|
||||
private string CreateCsv(TransactionListViewModel tlvm, string currentConnectorName)
|
||||
{
|
||||
StringBuilder csv = new StringBuilder(8192);
|
||||
csv.Append(EscapeCsvValue(_localizer["Connector"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["StartTime"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["StartTag"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["StartMeter"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["StopTime"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["StopTag"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["StopMeter"]));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(_localizer["ChargeSum"]));
|
||||
|
||||
if (tlvm != null && tlvm.Transactions != null)
|
||||
{
|
||||
foreach (Transaction t in tlvm.Transactions)
|
||||
{
|
||||
string startTag = t.StartTagId;
|
||||
string stopTag = t.StopTagId;
|
||||
if (!string.IsNullOrEmpty(t.StartTagId) && tlvm.ChargeTags != null && tlvm.ChargeTags.ContainsKey(t.StartTagId))
|
||||
{
|
||||
startTag = tlvm.ChargeTags[t.StartTagId]?.TagName;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(t.StopTagId) && tlvm.ChargeTags != null && tlvm.ChargeTags.ContainsKey(t.StopTagId))
|
||||
{
|
||||
stopTag = tlvm.ChargeTags[t.StopTagId]?.TagName;
|
||||
}
|
||||
|
||||
csv.AppendLine();
|
||||
csv.Append(EscapeCsvValue(currentConnectorName));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(t.StartTime.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(startTag));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(string.Format("{0:0.0##}", t.MeterStart)));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(((t.StopTime != null) ? t.StopTime.Value.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") : string.Empty)));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(stopTag));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(((t.MeterStop != null) ? string.Format("{0:0.0##}", t.MeterStop) : string.Empty)));
|
||||
csv.Append(CSV_Seperator);
|
||||
csv.Append(EscapeCsvValue(((t.MeterStop != null) ? string.Format("{0:0.0##}", (t.MeterStop - t.MeterStart)) : string.Empty)));
|
||||
}
|
||||
}
|
||||
|
||||
return csv.ToString();
|
||||
}
|
||||
|
||||
private string EscapeCsvValue(string value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(value))
|
||||
{
|
||||
if (value.Contains(CSV_Seperator))
|
||||
{
|
||||
if (value.Contains('"'))
|
||||
{
|
||||
// replace '"' with '""'
|
||||
value.Replace("\"", "\"\"");
|
||||
}
|
||||
|
||||
// put value in "
|
||||
value = string.Format("\"{0}\"", value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
334
OCPP.Core.Management/Controllers/HomeController.Index.cs
Normal file
334
OCPP.Core.Management/Controllers/HomeController.Index.cs
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class HomeController : BaseController
|
||||
{
|
||||
private readonly IStringLocalizer<HomeController> _localizer;
|
||||
|
||||
public HomeController(
|
||||
UserManager userManager,
|
||||
IStringLocalizer<HomeController> localizer,
|
||||
ILoggerFactory loggerFactory,
|
||||
IConfiguration config,
|
||||
OCPPCoreContext dbContext) : base(userManager, loggerFactory, config, dbContext)
|
||||
{
|
||||
_localizer = localizer;
|
||||
Logger = loggerFactory.CreateLogger<HomeController>();
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
Logger.LogTrace("Index: Loading charge points with latest transactions...");
|
||||
|
||||
OverviewViewModel overviewModel = new OverviewViewModel();
|
||||
overviewModel.ChargePoints = new List<ChargePointsOverviewViewModel>();
|
||||
try
|
||||
{
|
||||
Dictionary<string, ChargePointStatus> dictOnlineStatus = new Dictionary<string, ChargePointStatus>();
|
||||
#region Load online status from OCPP server
|
||||
string serverApiUrl = base.Config.GetValue<string>("ServerApiUrl");
|
||||
string apiKeyConfig = base.Config.GetValue<string>("ApiKey");
|
||||
if (!string.IsNullOrEmpty(serverApiUrl))
|
||||
{
|
||||
bool serverError = false;
|
||||
try
|
||||
{
|
||||
ChargePointStatus[] onlineStatusList = null;
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
if (!serverApiUrl.EndsWith('/'))
|
||||
{
|
||||
serverApiUrl += "/";
|
||||
}
|
||||
Uri uri = new Uri(serverApiUrl);
|
||||
uri = new Uri(uri, "Status");
|
||||
httpClient.Timeout = new TimeSpan(0, 0, 4); // use short timeout
|
||||
|
||||
// API-Key authentication?
|
||||
if (!string.IsNullOrWhiteSpace(apiKeyConfig))
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Add("X-API-Key", apiKeyConfig);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Index: No API-Key configured!");
|
||||
}
|
||||
|
||||
HttpResponseMessage response = await httpClient.GetAsync(uri);
|
||||
if (response.StatusCode == System.Net.HttpStatusCode.OK)
|
||||
{
|
||||
string jsonData = await response.Content.ReadAsStringAsync();
|
||||
if (!string.IsNullOrEmpty(jsonData))
|
||||
{
|
||||
onlineStatusList = JsonConvert.DeserializeObject<ChargePointStatus[]>(jsonData);
|
||||
overviewModel.ServerConnection = true;
|
||||
|
||||
if (onlineStatusList != null)
|
||||
{
|
||||
foreach(ChargePointStatus cps in onlineStatusList)
|
||||
{
|
||||
if (!dictOnlineStatus.TryAdd(cps.Id, cps))
|
||||
{
|
||||
Logger.LogError("Index: Online charge point status (ID={0}) could not be added to dictionary", cps.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("Index: Result of status web request is empty");
|
||||
serverError = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError("Index: Result of status web request => httpStatus={0}", response.StatusCode);
|
||||
serverError = true;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInformation("Index: Result of status web request => Length={0}", onlineStatusList?.Length);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Index: Error in status web request => {0}", exp.Message);
|
||||
serverError = true;
|
||||
}
|
||||
|
||||
if (serverError)
|
||||
{
|
||||
ViewBag.ErrorMsg = _localizer["ErrorOCPPServer"];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
// List of charge point status (OCPP messages) with latest transaction (if one exist)
|
||||
var connectorStatusViewList = DbContext.ConnectorStatuses
|
||||
.GroupJoin(
|
||||
DbContext.Transactions,
|
||||
cs => new { cs.ChargePointId, cs.ConnectorId },
|
||||
t => new { t.ChargePointId, t.ConnectorId },
|
||||
(cs, transactions) => new { cs, transactions }
|
||||
)
|
||||
.SelectMany(
|
||||
x => x.transactions.DefaultIfEmpty(),
|
||||
(x, transaction) => new ConnectorStatusView
|
||||
{
|
||||
ChargePointId = x.cs.ChargePointId,
|
||||
ConnectorId = x.cs.ConnectorId,
|
||||
ConnectorName = x.cs.ConnectorName,
|
||||
LastStatus = x.cs.LastStatus,
|
||||
LastStatusTime = x.cs.LastStatusTime,
|
||||
LastMeter = x.cs.LastMeter,
|
||||
LastMeterTime = x.cs.LastMeterTime,
|
||||
TransactionId = (int?)transaction.TransactionId,
|
||||
StartTagId = transaction.StartTagId,
|
||||
StartTime = transaction.StartTime,
|
||||
MeterStart = transaction.MeterStart,
|
||||
StartResult = transaction.StartResult,
|
||||
StopTagId = transaction.StopTagId,
|
||||
StopTime = transaction.StopTime,
|
||||
MeterStop = transaction.MeterStop,
|
||||
StopReason = transaction.StopReason
|
||||
}
|
||||
)
|
||||
.Where(x => x.TransactionId == null ||
|
||||
x.TransactionId == DbContext.Transactions
|
||||
.Where(t => t.ChargePointId == x.ChargePointId && t.ConnectorId == x.ConnectorId)
|
||||
.Select(t => t.TransactionId)
|
||||
.Max())
|
||||
.ToList();
|
||||
|
||||
|
||||
// Count connectors for every charge point (=> naming scheme)
|
||||
Dictionary<string, int> dictConnectorCount = new Dictionary<string, int>();
|
||||
foreach (ConnectorStatusView csv in connectorStatusViewList)
|
||||
{
|
||||
if (dictConnectorCount.ContainsKey(csv.ChargePointId))
|
||||
{
|
||||
// > 1 connector
|
||||
dictConnectorCount[csv.ChargePointId] = dictConnectorCount[csv.ChargePointId] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// first connector
|
||||
dictConnectorCount.Add(csv.ChargePointId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// List of configured charge points
|
||||
List<ChargePoint> dbChargePoints = DbContext.ChargePoints.ToList<ChargePoint>();
|
||||
if (dbChargePoints != null)
|
||||
{
|
||||
// Iterate through all charge points in database
|
||||
foreach (ChargePoint cp in dbChargePoints)
|
||||
{
|
||||
ChargePointStatus cpOnlineStatus = null;
|
||||
dictOnlineStatus.TryGetValue(cp.ChargePointId, out cpOnlineStatus);
|
||||
|
||||
// Preference: Check for connectors status in database
|
||||
bool foundConnectorStatus = false;
|
||||
if (connectorStatusViewList != null)
|
||||
{
|
||||
foreach (ConnectorStatusView connStatus in connectorStatusViewList)
|
||||
{
|
||||
if (string.Equals(cp.ChargePointId, connStatus.ChargePointId, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
foundConnectorStatus = true;
|
||||
|
||||
ChargePointsOverviewViewModel cpovm = new ChargePointsOverviewViewModel();
|
||||
cpovm.ChargePointId = cp.ChargePointId;
|
||||
cpovm.ConnectorId = connStatus.ConnectorId;
|
||||
if (string.IsNullOrWhiteSpace(connStatus.ConnectorName))
|
||||
{
|
||||
// No connector name specified => use default
|
||||
if (dictConnectorCount.ContainsKey(cp.ChargePointId) &&
|
||||
dictConnectorCount[cp.ChargePointId] > 1)
|
||||
{
|
||||
// more than 1 connector => "<charge point name>:<connector no.>"
|
||||
cpovm.Name = $"{cp.Name}:{connStatus.ConnectorId}";
|
||||
}
|
||||
else
|
||||
{
|
||||
// only 1 connector => "<charge point name>"
|
||||
cpovm.Name = cp.Name;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Connector has name override name specified
|
||||
cpovm.Name = connStatus.ConnectorName;
|
||||
}
|
||||
cpovm.Online = cpOnlineStatus != null;
|
||||
cpovm.ConnectorStatus = ConnectorStatusEnum.Undefined;
|
||||
OnlineConnectorStatus onlineConnectorStatus = null;
|
||||
if (cpOnlineStatus != null &&
|
||||
cpOnlineStatus.OnlineConnectors != null &&
|
||||
cpOnlineStatus.OnlineConnectors.ContainsKey(connStatus.ConnectorId))
|
||||
{
|
||||
onlineConnectorStatus = cpOnlineStatus.OnlineConnectors[connStatus.ConnectorId];
|
||||
cpovm.ConnectorStatus = onlineConnectorStatus.Status;
|
||||
Logger.LogTrace("Index: Found online status for CP='{0}' / Connector='{1}' / Status='{2}'", cpovm.ChargePointId, cpovm.ConnectorId, cpovm.ConnectorStatus);
|
||||
}
|
||||
|
||||
if (connStatus.TransactionId.HasValue)
|
||||
{
|
||||
cpovm.MeterStart = connStatus.MeterStart.Value;
|
||||
cpovm.MeterStop = connStatus.MeterStop;
|
||||
cpovm.StartTime = connStatus.StartTime;
|
||||
cpovm.StopTime = connStatus.StopTime;
|
||||
|
||||
if (cpovm.ConnectorStatus == ConnectorStatusEnum.Undefined)
|
||||
{
|
||||
// default status: active transaction or not?
|
||||
cpovm.ConnectorStatus = (cpovm.StopTime.HasValue) ? ConnectorStatusEnum.Available : ConnectorStatusEnum.Occupied;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpovm.MeterStart = -1;
|
||||
cpovm.MeterStop = -1;
|
||||
cpovm.StartTime = null;
|
||||
cpovm.StopTime = null;
|
||||
|
||||
if (cpovm.ConnectorStatus == ConnectorStatusEnum.Undefined)
|
||||
{
|
||||
// default status: Available
|
||||
cpovm.ConnectorStatus = ConnectorStatusEnum.Available;
|
||||
}
|
||||
}
|
||||
|
||||
// Add current charge data to view model
|
||||
if (cpovm.ConnectorStatus == ConnectorStatusEnum.Occupied &&
|
||||
onlineConnectorStatus != null)
|
||||
{
|
||||
string currentCharge = string.Empty;
|
||||
if (onlineConnectorStatus.ChargeRateKW != null)
|
||||
{
|
||||
currentCharge = string.Format("{0:0.0}kW", onlineConnectorStatus.ChargeRateKW.Value);
|
||||
}
|
||||
if (onlineConnectorStatus.SoC != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(currentCharge)) currentCharge += " | ";
|
||||
currentCharge += string.Format("{0:0}%", onlineConnectorStatus.SoC.Value);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(currentCharge))
|
||||
{
|
||||
cpovm.CurrentChargeData = currentCharge;
|
||||
}
|
||||
}
|
||||
|
||||
overviewModel.ChargePoints.Add(cpovm);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Fallback: assume 1 connector and show main charge point
|
||||
if (foundConnectorStatus == false)
|
||||
{
|
||||
// no connector status found in DB => show configured charge point in overview
|
||||
ChargePointsOverviewViewModel cpovm = new ChargePointsOverviewViewModel();
|
||||
cpovm.ChargePointId = cp.ChargePointId;
|
||||
cpovm.ConnectorId = 0;
|
||||
cpovm.Name = cp.Name;
|
||||
cpovm.Comment = cp.Comment;
|
||||
cpovm.Online = cpOnlineStatus != null;
|
||||
cpovm.ConnectorStatus = ConnectorStatusEnum.Undefined;
|
||||
overviewModel.ChargePoints.Add(cpovm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogInformation("Index: Found {0} charge points / connectors", overviewModel.ChargePoints?.Count);
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Index: Error loading charge points from database");
|
||||
TempData["ErrMessage"] = exp.Message;
|
||||
return RedirectToAction("Error", new { Id = "" });
|
||||
}
|
||||
|
||||
return View(overviewModel);
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
}
|
||||
127
OCPP.Core.Management/Controllers/HomeController.Transactions.cs
Normal file
127
OCPP.Core.Management/Controllers/HomeController.Transactions.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* OCPP.Core - https://github.com/dallmann-consulting/OCPP.Core
|
||||
* Copyright (C) 2020-2021 dallmann consulting GmbH.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OCPP.Core.Database;
|
||||
using OCPP.Core.Management.Models;
|
||||
|
||||
namespace OCPP.Core.Management.Controllers
|
||||
{
|
||||
public partial class HomeController : BaseController
|
||||
{
|
||||
[Authorize]
|
||||
public IActionResult Transactions(string Id, string ConnectorId)
|
||||
{
|
||||
Logger.LogTrace("Transactions: Loading charge point transactions...");
|
||||
|
||||
int currentConnectorId = -1;
|
||||
int.TryParse(ConnectorId, out currentConnectorId);
|
||||
|
||||
TransactionListViewModel tlvm = new TransactionListViewModel();
|
||||
tlvm.CurrentChargePointId = Id;
|
||||
tlvm.CurrentConnectorId = currentConnectorId;
|
||||
tlvm.ConnectorStatuses = new List<ConnectorStatus>();
|
||||
tlvm.Transactions = new List<Transaction>();
|
||||
|
||||
try
|
||||
{
|
||||
string ts = Request.Query["t"];
|
||||
int days = 30;
|
||||
if (ts == "2")
|
||||
{
|
||||
// 90 days
|
||||
days = 90;
|
||||
tlvm.Timespan = 2;
|
||||
}
|
||||
else if (ts == "3")
|
||||
{
|
||||
// 365 days
|
||||
days = 365;
|
||||
tlvm.Timespan = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 30 days
|
||||
days = 30;
|
||||
tlvm.Timespan = 1;
|
||||
}
|
||||
|
||||
Logger.LogTrace("Transactions: Loading charge points...");
|
||||
tlvm.ChargePoints = DbContext.ChargePoints.ToList<ChargePoint>();
|
||||
|
||||
Logger.LogTrace("Transactions: Loading charge points connectors...");
|
||||
tlvm.ConnectorStatuses = DbContext.ConnectorStatuses.ToList<ConnectorStatus>();
|
||||
|
||||
// Count connectors for every charge point (=> naming scheme)
|
||||
Dictionary<string, int> dictConnectorCount = new Dictionary<string, int>();
|
||||
foreach (ConnectorStatus cs in tlvm.ConnectorStatuses)
|
||||
{
|
||||
if (dictConnectorCount.ContainsKey(cs.ChargePointId))
|
||||
{
|
||||
// > 1 connector
|
||||
dictConnectorCount[cs.ChargePointId] = dictConnectorCount[cs.ChargePointId] + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// first connector
|
||||
dictConnectorCount.Add(cs.ChargePointId, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// load charge tags for name resolution
|
||||
Logger.LogTrace("Transactions: Loading charge tags...");
|
||||
List<ChargeTag> chargeTags = DbContext.ChargeTags.ToList<ChargeTag>();
|
||||
tlvm.ChargeTags = new Dictionary<string, ChargeTag>();
|
||||
if (chargeTags != null)
|
||||
{
|
||||
foreach(ChargeTag tag in chargeTags)
|
||||
{
|
||||
tlvm.ChargeTags.Add(tag.TagId, tag);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(tlvm.CurrentChargePointId))
|
||||
{
|
||||
Logger.LogTrace("Transactions: Loading charge point transactions...");
|
||||
tlvm.Transactions = DbContext.Transactions
|
||||
.Where(t => t.ChargePointId == tlvm.CurrentChargePointId &&
|
||||
t.ConnectorId == tlvm.CurrentConnectorId &&
|
||||
t.StartTime >= DateTime.UtcNow.AddDays(-1 * days))
|
||||
.OrderByDescending(t => t.TransactionId)
|
||||
.ToList<Transaction>();
|
||||
}
|
||||
}
|
||||
catch (Exception exp)
|
||||
{
|
||||
Logger.LogError(exp, "Transactions: Error loading charge points from database");
|
||||
}
|
||||
|
||||
return View(tlvm);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user