Files
DP44/DataPRO/CanFDApiProxy/CANFD.cs
2026-04-17 14:55:32 -04:00

508 lines
26 KiB
C#

using CANFDApiProxy.Interfaces;
using CANFDApiProxy.Messages;
using CANFDApiProxy.Requests;
using CsvHelper.Configuration;
using DTS.Common.Classes.DASFactory;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using System.Threading.Tasks;
namespace CANFDApiProxy
{
public sealed class CANFD : ICANFDApi
{
private static readonly Lazy<CANFD> lazy = new Lazy<CANFD>(() => new CANFD());
public static CANFD API { get { return lazy.Value; } }
private CANFD()
{
}
public async Task<UsbTreeMessage> GetUsbTree(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.UsbTree, cancellationToken);
var response = JsonConvert.DeserializeObject<UsbTreeMessage>(jsonResponse);
return response;
}
public async Task<BatteryMessage> GetBattery(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Battery, cancellationToken);
var response = JsonConvert.DeserializeObject<BatteryMessage>(jsonResponse);
return response;
}
/// <summary>
/// gets results of BIST end point on unit
/// can throw units
/// </summary>
public async Task<DiagnosticMessageRow[]> GetBIST(string deviceHost, CancellationToken cancellationToken)
{
var request = new DiagnosticsMessageRequest() { format = "csv" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Diagnostics, request, cancellationToken);
var config = new CsvConfiguration(CultureInfo.InvariantCulture) { PrepareHeaderForMatch = args => args.Header.ToLower(), };
using (var reader = new StringReader(jsonResponse.ToString()))
{
using (var csv = new CsvHelper.CsvReader(reader, config))
{
var records = csv.GetRecords<DiagnosticMessageRow>().ToArray();
return records;
}
}
}
public async Task<CalibrationMessage> GetCalibrationDate(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.CalibrationDate, cancellationToken);
var response = JsonConvert.DeserializeObject<CalibrationMessage>(jsonResponse);
return response;
}
public async Task<SerialMessage> GetSerial(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Serial, cancellationToken);
var response = JsonConvert.DeserializeObject<SerialMessage>(jsonResponse);
return response;
}
public async Task<LEDsMessage> GetLEDs(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.LEDs, cancellationToken);
var canInternal = JsonConvert.DeserializeObject<CANInfoInternal>(jsonResponse);
var ledsMessage = new LEDsMessage();
List<LED> leds = new List<LED>
{
new LED("can1",canInternal.can1.blue, canInternal.can1.green, canInternal.can1.red),
new LED("can2",canInternal.can2.blue, canInternal.can2.green, canInternal.can2.red),
new LED("can3",canInternal.can3.blue, canInternal.can3.green, canInternal.can3.red),
new LED("can4",canInternal.can4.blue, canInternal.can4.green, canInternal.can4.red)
};
ledsMessage.LEDs = leds;
ledsMessage.Status = canInternal.status;
ledsMessage.Battery = canInternal.battery;
ledsMessage.Pwr = canInternal.pwr;
ledsMessage.Sts = canInternal.sts;
return ledsMessage;
}
public async Task<CANInfoMessage> GetCANInfo(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.CANInfo, cancellationToken);
var canInternal = JsonConvert.DeserializeObject<CANInfoInternal>(jsonResponse);
var canInfoMessage = new CANInfoMessage();
List<CANInfo> list = new List<CANInfo> { new CANInfo("can1", canInternal.can1.info),
new CANInfo("can2", canInternal.can2.info),
new CANInfo("can3", canInternal.can3.info),
new CANInfo("can4", canInternal.can4.info)};
canInfoMessage.CANInfoList = list;
return canInfoMessage;
}
public async Task<CANStateMessage> GetCANState(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.CANState, cancellationToken);
var canInternal = JsonConvert.DeserializeObject<CANInfoInternal>(jsonResponse);
var canMessage = new CANStateMessage();
List<CANState> list = new List<CANState> { new CANState("can1", canInternal.can1.state,canInternal.can1.last_updated ),
new CANState("can2", canInternal.can2.state,canInternal.can2.last_updated ),
new CANState("can3", canInternal.can3.state,canInternal.can3.last_updated ),
new CANState("can4", canInternal.can4.state,canInternal.can4.last_updated )};
canMessage.CANStateList = list;
return canMessage;
}
public async Task<CANStatsMessage> GetCANStats(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.CANStats, cancellationToken);
var canInternal = JsonConvert.DeserializeObject<CANInfoInternal>(jsonResponse);
var canMessage = new CANStatsMessage();
List<CANStats> list = new List<CANStats> {
new CANStats("can1", canInternal.can1.std_data,canInternal.can1.std_remote,canInternal.can1.ext_data,canInternal.can1.ext_remote,canInternal.can1.err_frame,canInternal.can1.bus_load,canInternal.can1.overruns, canInternal.can1.last_updated ),
new CANStats("can2", canInternal.can2.std_data,canInternal.can2.std_remote,canInternal.can2.ext_data,canInternal.can2.ext_remote,canInternal.can2.err_frame,canInternal.can2.bus_load,canInternal.can2.overruns, canInternal.can2.last_updated ),
new CANStats("can3", canInternal.can3.std_data,canInternal.can3.std_remote,canInternal.can3.ext_data,canInternal.can3.ext_remote,canInternal.can3.err_frame,canInternal.can3.bus_load,canInternal.can3.overruns, canInternal.can3.last_updated ),
new CANStats("can4", canInternal.can4.std_data,canInternal.can4.std_remote,canInternal.can4.ext_data,canInternal.can4.ext_remote,canInternal.can4.err_frame,canInternal.can4.bus_load,canInternal.can4.overruns, canInternal.can4.last_updated )};
canMessage.CANStatsList = list;
return canMessage;
}
public async Task<CANConfigMessage> GetCANConfig(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.CANConfig, cancellationToken);
var canInternal = JsonConvert.DeserializeObject<CANInfoInternal>(jsonResponse);
var canMessage = new CANConfigMessage();
List<CANConfig> list = new List<CANConfig> {
new CANConfig("can1", canInternal.can1.base_or_arb_bitrate,canInternal.can1.base_or_arb_sjw, canInternal.can1.data_bitrate, canInternal.can1.data_sjw,canInternal.can1.filetype, canInternal.can1.included, canInternal.can1.is_fd ),
new CANConfig("can2", canInternal.can2.base_or_arb_bitrate,canInternal.can2.base_or_arb_sjw, canInternal.can2.data_bitrate, canInternal.can2.data_sjw,canInternal.can2.filetype, canInternal.can2.included, canInternal.can2.is_fd ),
new CANConfig("can3", canInternal.can3.base_or_arb_bitrate,canInternal.can3.base_or_arb_sjw, canInternal.can3.data_bitrate, canInternal.can3.data_sjw,canInternal.can3.filetype, canInternal.can3.included, canInternal.can3.is_fd ),
new CANConfig("can4", canInternal.can4.base_or_arb_bitrate,canInternal.can4.base_or_arb_sjw, canInternal.can4.data_bitrate, canInternal.can4.data_sjw,canInternal.can4.filetype, canInternal.can4.included, canInternal.can4.is_fd )};
canMessage.CANConfigList = list;
canMessage.Pipe = canInternal.pipe;
return canMessage;
}
public async Task<DeviceInfoMessage> GetDeviceInfo(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.DeviceInfo, cancellationToken);
var response = JsonConvert.DeserializeObject<DeviceInfoMessage>(jsonResponse);
return response;
}
public async Task<NtpMessage> GetNtp(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Ntp, cancellationToken);
var response = JsonConvert.DeserializeObject<NtpMessage>(jsonResponse);
return response;
}
public async Task<PowerMessage> GetPower(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Power, cancellationToken);
var response = JsonConvert.DeserializeObject<PowerMessage>(jsonResponse);
return response;
}
public async Task<ServicesMessage> GetServices(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Services, cancellationToken);
var response = JsonConvert.DeserializeObject<ServicesMessage>(jsonResponse);
return response;
}
public async Task<NetworkMessage> GetNetwork(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Network, cancellationToken);
var response = JsonConvert.DeserializeObject<NetworkMessage>(jsonResponse);
return response;
}
public async Task<ClocksMessage> GetClocks(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Clocks, cancellationToken);
var response = JsonConvert.DeserializeObject<ClocksMessage>(jsonResponse);
return response;
}
public async Task<EventPinMessage> GetEventPin(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.EventPin, cancellationToken);
var response = JsonConvert.DeserializeObject<EventPinMessage>(jsonResponse);
return response;
}
public async Task<RecordingMessage> GetRecording(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.Recording, cancellationToken);
var response = JsonConvert.DeserializeObject<RecordingMessage>(jsonResponse);
return response;
}
public async Task<UsbStatsMessage> GetUsbStats(string deviceHost, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.GetResourceAsync(deviceHost, CommandName.UsbStats, cancellationToken);
var response = JsonConvert.DeserializeObject<UsbStatsMessage>(jsonResponse);
return response;
}
public async Task<SerialMessage> SetSerial(string deviceHost, SerialRequest serialRequest, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Serial, serialRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<SerialMessage>(jsonResponse);
return response;
}
public async Task<PowerMessage> SetPowerOff(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "off" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Power, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<PowerMessage>(jsonResponse);
return response;
}
public async Task<PowerMessage> SetPowerReboot(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "reboot" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Power, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<PowerMessage>(jsonResponse);
return response;
}
public async Task<CANConfigMessage> SetCANConfig(string deviceHost, CANConfigRequest canConfigRequest, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.CANConfig, canConfigRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<CANConfigMessage>(jsonResponse);
return response;
}
public async Task<LEDsPostMessage> SetLEDs(string deviceHost, LedName led, LedCmd cmd, LedColor color, CancellationToken cancellationToken)
{
var request = new LEDsRequest { cmd = cmd.ToString(), color = color.ToString(), led = led.ToString() };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.LEDs, request, cancellationToken);
var response = JsonConvert.DeserializeObject<LEDsPostMessage>(jsonResponse);
return response;
}
public async Task<ClocksMessage> SetClocks(string deviceHost, DateTime dateTime, CancellationToken cancellationToken)
{
var request = new ClocksRequest { cmd = "set", time = dateTime.ToString("yyyy-MM-dd HH:mm:ss") };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Clocks, request, cancellationToken);
var response = JsonConvert.DeserializeObject<ClocksMessage>(jsonResponse);
return response;
}
public async Task<ClocksMessage> SyncClocks(string deviceHost, CancellationToken cancellationToken)
{
var request = new ClocksRequest { cmd = "sync" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Clocks, request, cancellationToken);
var response = JsonConvert.DeserializeObject<ClocksMessage>(jsonResponse);
return response;
}
public async Task<RecordingMessage> SetRecordingStart(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "start" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Recording, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<RecordingMessage>(jsonResponse);
return response;
}
public async Task<RecordingMessage> SetRecordingTriggerCheck_Quick(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "triggercheck_quick" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Recording, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<RecordingMessage>(jsonResponse);
return response;
}
public async Task<RecordingMessage> SetRecordingStop(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "stop" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Recording, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<RecordingMessage>(jsonResponse);
return response;
}
public async Task<NetworkMessage> SetNetwork(string deviceHost, NetworkRequest networkRequest, CancellationToken cancellationToken)
{
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.Network, networkRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<NetworkMessage>(jsonResponse);
return response;
}
public async Task<EventPinMessage> SetEventPinArm(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "arm" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.EventPin, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<EventPinMessage>(jsonResponse);
return response;
}
public async Task<EventPinMessage> SetEventPinDisarm(string deviceHost, CancellationToken cancellationToken)
{
var powerRequest = new CanPostRequest { cmd = "disarm" };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.EventPin, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<EventPinMessage>(jsonResponse);
return response;
}
/// <summary>
/// Delete the file or directory from the device
/// </summary>
/// <param name="deviceHost">device ip address</param>
/// <param name="usbPath">usb path of the file or folder which you want to delete from the device</param>
/// <param name="cancellationToken"></param>
/// <returns>status message</returns>
/// <exception cref="ArgumentException">exception on invalid arguments</exception>
public async Task<StatusMessage> Delete(string deviceHost, string usbPath, CancellationToken cancellationToken)
{
VerifyUsbPathIsNotNull(usbPath);
return await DeleteAsync(deviceHost, usbPath, cancellationToken);
}
private static void VerifyUsbPathIsNotNull(string usbPath)
{
if (string.IsNullOrEmpty(usbPath))
{
throw new ArgumentException("usbPAth cannot be null or empty", "usbPath");
}
}
private static async Task<StatusMessage> DeleteAsync(string deviceHost, string usbPath, CancellationToken cancellationToken)
{
var powerRequest = new FileRequest { cmd = "delete", path = usbPath };
var jsonResponse = await RESTWrapper.PostResourceAsync(deviceHost, CommandName.File, powerRequest, cancellationToken);
var response = JsonConvert.DeserializeObject<StatusMessage>(jsonResponse);
return response;
}
/// <summary>
/// Dwonload from file or directory, by specifying the usb path to file or directory.
/// for directory the REST api returns the zip file of the directory.
/// </summary>
/// <param name="deviceHost">device ip address</param>
/// <param name="usbPath">usb path of the download file or directory like /media/usb0/Logs/2025-07-30_15-44/ServiceLogs.1.log or /media/usb0/Logs/2025-07-30_15-44</param>
/// <param name="destinationDirectory">local destination directory</param>
/// <param name="timeOut">timeout for download</param>
/// <param name="cancellationToken">token to cancel the download</param>
/// <returns></returns>
/// <exception cref="ArgumentException">error of not valid arguments</exception>
public async Task Download(string deviceHost, string usbPath, string destinationDirectory, TimeSpan timeOut, CancellationToken cancellationToken)
{
VerifyUsbPathIsNotNull(usbPath);
VerifyDestinationIsNotNull(destinationDirectory);
VerifyDestinationExist(destinationDirectory);
await DownloadProcess(deviceHost, usbPath, destinationDirectory, timeOut, cancellationToken);
}
private async Task DownloadProcess(string deviceHost, string usbPath, string destinationDirectory, TimeSpan timeOut, CancellationToken cancellationToken)
{
var oldTimeout = RESTWrapper.Timeout;
try
{
RESTWrapper.Timeout = timeOut;
string filePath = BuildFilePath(usbPath, destinationDirectory);
var downloadRequest = new FileRequest { cmd = "download", path = usbPath };
var response = await RESTWrapper.SendResourceReadAsStreamAsync(deviceHost, CommandName.File, downloadRequest, timeOut, cancellationToken);
await RESTWrapper.WriteStreamToFileAsync(response, filePath);
}
finally
{
RESTWrapper.Timeout = oldTimeout;
}
}
private static void VerifyDestinationExist(string destinationDirectory)
{
if (!Directory.Exists(destinationDirectory))
{
throw new ArgumentException($"directory {destinationDirectory} does not exist", "destinationDirectory");
}
}
private static void VerifyDestinationIsNotNull(string destinationDirectory)
{
if (string.IsNullOrEmpty(destinationDirectory))
{
throw new ArgumentException("destinationDirectory cannot be null or empty", "destinationDirectory");
}
}
/// <summary>
/// upload the specified source file to device
/// </summary>
/// <param name="deviceHost">device ip address</param>
/// <param name="uploadUsbPath">ubpath for upload like /media/usb0/Uploads </param>
/// <param name="sourcefile">file path that you want to upload to device</param>
/// <param name="timeOut">timeout</param>
/// <param name="cancellationToken">token to cancel upload</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public async Task<StatusMessage> Upload(string deviceHost, string uploadUsbPath, string sourcefile, TimeSpan timeOut, CancellationToken cancellationToken)
{
VerifyUploadUsbPathIsNotEmpty(uploadUsbPath);
VerifySourceIsNotEmpty(sourcefile);
VerifySourceExist(sourcefile);
return await UploadProcess(deviceHost, uploadUsbPath, sourcefile, timeOut, cancellationToken);
}
private static async Task<StatusMessage> UploadProcess(string deviceHost, string uploadUsbPath, string sourcefile, TimeSpan timeOut, CancellationToken cancellationToken)
{
var oldTimeout = RESTWrapper.Timeout;
try
{
RESTWrapper.Timeout = timeOut;
MultipartFormDataContent multipart = new MultipartFormDataContent();
HttpContent cmd = new StringContent("upload");
HttpContent path = new StringContent(uploadUsbPath);
multipart.Add(cmd, "cmd");
multipart.Add(path, "path");
byte[] data = File.ReadAllBytes(sourcefile);
HttpContent fileContent = new StreamContent(new MemoryStream(data));
multipart.Add(fileContent, "file", Path.GetFileName(sourcefile));
var jsonResponse = await RESTWrapper.PostResourceReadAsStringAsync(deviceHost, CommandName.File, multipart, timeOut, cancellationToken);
var response = JsonConvert.DeserializeObject<StatusMessage>(jsonResponse);
return response;
}
finally
{
RESTWrapper.Timeout = oldTimeout;
}
}
private static void VerifySourceExist(string sourcefile)
{
if (!File.Exists(sourcefile))
{
throw new ArgumentException($"file {sourcefile} does not exist", "sourcefile");
}
}
private static void VerifySourceIsNotEmpty(string sourcefile)
{
if (string.IsNullOrEmpty(sourcefile))
{
throw new ArgumentException("sourcefile cannot be null or empty", "sourcefile");
}
}
private static void VerifyUploadUsbPathIsNotEmpty(string uploadUsbPath)
{
if (string.IsNullOrEmpty(uploadUsbPath))
{
throw new ArgumentException("uploadUsbPath cannot be null or empty", "uploadUsbPath");
}
}
private bool IsDirectory(string fileOrDirectory)
{
var file = Path.GetExtension(fileOrDirectory);
return string.IsNullOrEmpty(file);
}
private string BuildFilePath(string usbPath, string destinationDirectory)
{
var pathSegments = usbPath.Split('/').ToList();
string fileName;
if (IsDirectory(pathSegments.Last()))
{
fileName = $"{pathSegments.Last()}.zip";
}
else
{
fileName = pathSegments.Last();
}
var filePath = Path.Combine(destinationDirectory, fileName);
return filePath;
}
}
}