This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,12 @@
{
"Version": 1,
"WorkspaceRootPath": "D:\\DTS\\Code\\DP\\BRANCH_MAINT_4_04\\DataPRO\\",
"Documents": [],
"DocumentGroupContainers": [
{
"Orientation": 0,
"VerticalTabListWidth": 256,
"DocumentGroups": []
}
]
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
DataPRO/.vs/slnx.sqlite Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,46 @@
using CANFDApiProxy.Messages;
using CANFDApiProxy.Requests;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CANFDApiProxy.Interfaces
{
public interface ICANFDApi
{
Task<UsbTreeMessage> GetUsbTree(string deviceHost, CancellationToken cancellationToken);
Task<UsbStatsMessage> GetUsbStats(string deviceHost, CancellationToken cancellationToken);
Task<SerialMessage> GetSerial(string deviceHost, CancellationToken cancellationToken);
Task<LEDsMessage> GetLEDs(string deviceHost, CancellationToken cancellationToken);
Task<ClocksMessage> GetClocks(string deviceHost, CancellationToken cancellationToken);
Task<EventPinMessage> GetEventPin(string deviceHost, CancellationToken cancellationToken);
Task<CANConfigMessage> GetCANConfig(string deviceHost, CancellationToken cancellationToken);
Task<CANInfoMessage> GetCANInfo(string deviceHost, CancellationToken cancellationToken);
Task<CANStateMessage> GetCANState(string deviceHost, CancellationToken cancellationToken);
Task<CANStatsMessage> GetCANStats(string deviceHost, CancellationToken cancellationToken);
Task<BatteryMessage> GetBattery(string deviceHost, CancellationToken cancellationToken);
Task<ServicesMessage> GetServices(string deviceHost, CancellationToken cancellationToken);
Task<NtpMessage> GetNtp(string deviceHost, CancellationToken cancellationToken);
Task<PowerMessage> GetPower(string deviceHost, CancellationToken cancellationToken);
Task<DeviceInfoMessage> GetDeviceInfo(string deviceHost, CancellationToken cancellationToken);
Task<RecordingMessage> GetRecording(string deviceHost, CancellationToken cancellationToken);
Task<NetworkMessage> GetNetwork(string deviceHost, CancellationToken cancellationToken);
Task<SerialMessage> SetSerial(string deviceHost, SerialRequest serialRequest, CancellationToken cancellationToken);
Task<LEDsPostMessage> SetLEDs(string deviceHost, LedName led, LedCmd cmd, LedColor color, CancellationToken cancellationToken);
Task<ClocksMessage> SetClocks(string deviceHost,DateTime dateTime, CancellationToken cancellationToken);
Task<EventPinMessage> SetEventPinArm(string deviceHost, CancellationToken cancellationToken);
Task<EventPinMessage> SetEventPinDisarm(string deviceHost, CancellationToken cancellationToken);
Task<ClocksMessage> SyncClocks(string deviceHost, CancellationToken cancellationToken);
Task<CANConfigMessage> SetCANConfig(string deviceHost, CANConfigRequest canConfigRequest, CancellationToken cancellationToken);
Task<PowerMessage> SetPowerOff(string deviceHost, CancellationToken cancellationToken);
Task<PowerMessage> SetPowerReboot(string deviceHost, CancellationToken cancellationToken);
Task<RecordingMessage> SetRecordingStart(string deviceHost, CancellationToken cancellationToken);
Task<RecordingMessage> SetRecordingStop(string deviceHost, CancellationToken cancellationToken);
Task<NetworkMessage> SetNetwork(string deviceHost, NetworkRequest networkRequest, CancellationToken cancellationToken);
Task Download(string deviceHost, string usbPath, string destinationDirectory, TimeSpan timeOut, CancellationToken cancellationToken);
Task<StatusMessage> Upload(string deviceHost, string uploadUsbPath, string sourcefile, TimeSpan timeOut, CancellationToken cancellationToken);
Task<StatusMessage> Delete(string deviceHost, string usbPath, CancellationToken cancellationToken);
}
}

View File

@@ -0,0 +1,101 @@
namespace CANFDApiProxy.Messages
{
public class UsbStatsMessage
{
public Filesystem Filesystem { get; set; }
public Swissbit Swissbit { get; set; }
public Traffic Traffic { get; set; }
}
public class Filesystem
{
public string avail { get; set; }
public string filesystem { get; set; }
public string mounted { get; set; }
public string size { get; set; }
public string type { get; set; }
public string use_pct { get; set; }
public string used { get; set; }
}
public class Swissbit
{
public Lifetime_Info lifetime_info { get; set; }
public string model { get; set; }
public string path { get; set; }
public string serial { get; set; }
}
public class Lifetime_Info
{
public string controller_revision { get; set; }
public int correctable_ecc_errors { get; set; }
public Erase_Info[] erase_info { get; set; }
public string firmware_revision { get; set; }
public int flash_lbas_written { get; set; }
public bool global_bad_block_management { get; set; }
public bool global_wear_leveling { get; set; }
public bool overall_health_status { get; set; }
public int power_on_counter { get; set; }
public Spare_Block_Info spare_block_info { get; set; }
public int temperature_current { get; set; }
public int temperature_max { get; set; }
public int temperature_min { get; set; }
public int total_ecc_errors { get; set; }
public int total_erase_count { get; set; }
}
public class Spare_Block_Info
{
public bool count_prefail { get; set; }
public int count_threshold { get; set; }
public bool count_valid { get; set; }
public int count_value { get; set; }
public int minimum { get; set; }
public int number_of_units { get; set; }
public int[] per_unit_current { get; set; }
public int[] per_unit_initial { get; set; }
public int total_current { get; set; }
public int total_initial { get; set; }
public int worst_current { get; set; }
public int worst_initial { get; set; }
}
public class Erase_Info
{
public Average_Erase_Count average_erase_count { get; set; }
public int erase_count { get; set; }
public string flash_cell_mode { get; set; }
public Max_Erase_Count max_erase_count { get; set; }
public bool prefail { get; set; }
public Rated_Erase_Count rated_erase_count { get; set; }
public int threshold { get; set; }
public bool valid { get; set; }
}
public class Average_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Max_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Rated_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Traffic
{
public float average_mbps { get; set; }
public float current_mbps { get; set; }
public float mins_remaining { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace CANFDApiProxy.Messages
{
public class DeviceInfoMessage
{
public string Kernel_version { get; set; }
public string Os_release { get; set; }
public string Serial_number { get; set; }
public string Version_number { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Messages
{
public class LEDsPostMessage
{
public string status { get; set; }
public string reply { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Requests
{
internal class ClocksRequest
{
public string cmd { get; set; }
public string time { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
namespace CANFDApiProxy.Requests
{
public class CanConfigItem
{
public CanConfigItem(int base_or_arb_bitrate, int base_or_arb_sjw, int data_bitrate, int data_sjw, string filetype, bool included, bool is_fd)
{
this.base_or_arb_bitrate = base_or_arb_bitrate;
this.base_or_arb_sjw = base_or_arb_sjw;
this.data_bitrate = data_bitrate;
this.data_sjw = data_sjw;
this.filetype = filetype;
this.included = included;
this.is_fd = is_fd;
}
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
}
}

View File

@@ -0,0 +1,44 @@
using System.ComponentModel;
namespace CANFDApiProxy
{
internal enum CommandName
{
[Description("serial")]
Serial,
[Description("leds")]
LEDs,
[Description("battery")]
Battery,
[Description("can-info")]
CANInfo,
[Description("can-state")]
CANState,
[Description("can-stats")]
CANStats,
[Description("can-config")]
CANConfig,
[Description("device-info")]
DeviceInfo,
[Description("ntp")]
Ntp,
[Description("power")]
Power,
[Description("services")]
Services,
[Description("network")]
Network,
[Description("clocks")]
Clocks,
[Description("event-pin")]
EventPin,
[Description("recording")]
Recording,
[Description("usb-stats")]
UsbStats,
[Description("usb-tree")]
UsbTree,
[Description("file")]
File
}
}

View File

@@ -0,0 +1,117 @@
namespace CANFDApiProxy.Messages
{
public class UsbStatsMessage
{
public Filesystem Filesystem { get; set; }
public Swissbit Swissbit { get; set; }
public Traffic Traffic { get; set; }
public override string ToString()
{
return $"FS: {Filesystem}, SB: {Swissbit}, TR: {Traffic}";
}
}
public class Filesystem
{
public string avail { get; set; }
public string filesystem { get; set; }
public string mounted { get; set; }
public string size { get; set; }
public string type { get; set; }
public string use_pct { get; set; }
public string used { get; set; }
public override string ToString()
{
return $"avail: {avail}, size: {size}, use%: {use_pct}, used: {used}";
}
}
public class Swissbit
{
public Lifetime_Info lifetime_info { get; set; }
public string model { get; set; }
public string path { get; set; }
public string serial { get; set; }
public override string ToString()
{
return $"serial: {serial}, ecc: {lifetime_info.total_ecc_errors}";
}
}
public class Lifetime_Info
{
public string controller_revision { get; set; }
public int correctable_ecc_errors { get; set; }
public Erase_Info[] erase_info { get; set; }
public string firmware_revision { get; set; }
public int flash_lbas_written { get; set; }
public bool global_bad_block_management { get; set; }
public bool global_wear_leveling { get; set; }
public bool overall_health_status { get; set; }
public int power_on_counter { get; set; }
public Spare_Block_Info spare_block_info { get; set; }
public int temperature_current { get; set; }
public int temperature_max { get; set; }
public int temperature_min { get; set; }
public int total_ecc_errors { get; set; }
public int total_erase_count { get; set; }
}
public class Spare_Block_Info
{
public bool count_prefail { get; set; }
public int count_threshold { get; set; }
public bool count_valid { get; set; }
public int count_value { get; set; }
public int minimum { get; set; }
public int number_of_units { get; set; }
public int[] per_unit_current { get; set; }
public int[] per_unit_initial { get; set; }
public int total_current { get; set; }
public int total_initial { get; set; }
public int worst_current { get; set; }
public int worst_initial { get; set; }
}
public class Erase_Info
{
public Average_Erase_Count average_erase_count { get; set; }
public int erase_count { get; set; }
public string flash_cell_mode { get; set; }
public Max_Erase_Count max_erase_count { get; set; }
public bool prefail { get; set; }
public Rated_Erase_Count rated_erase_count { get; set; }
public int threshold { get; set; }
public bool valid { get; set; }
}
public class Average_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Max_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Rated_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Traffic
{
public float average_mbps { get; set; }
public float current_mbps { get; set; }
public float mins_remaining { get; set; }
public override string ToString()
{
return $"ave: {average_mbps}mbps, current: {current_mbps}mbps, remaining: {mins_remaining}mins";
}
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Requests
{
internal class FileRequest
{
public string cmd { get; set; }
public string path { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class EventPinMessage
{
public bool? Armed { get; set; }
public bool? Event { get; set; }
public bool? Event_pin { get; set; }
public string File_name { get; set; }
public string Ok { get; set; }
public string Reply { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http;
namespace CANFDApiProxy
{
public static class HttpClientFactory
{
private static IHttpClientFactory CreateHttpClientFactory()
{
var httpClientFactory = new ServiceCollection().AddHttpClient().BuildServiceProvider().GetRequiredService<IHttpClientFactory>();
return httpClientFactory;
}
public static HttpClient CreateHttpClient()
{
IHttpClientFactory httpClientFactory = CreateHttpClientFactory();
var httpClient = httpClientFactory.CreateClient();
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
return httpClient;
}
}
}

View File

@@ -0,0 +1,226 @@
using CANFDApiProxy.Messages;
using Newtonsoft.Json;
using System;
using System.CodeDom;
using System.ComponentModel;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CANFDApiProxy
{
internal static class RESTWrapper
{
/// <summary>
/// Get the description part of the enum
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
private static string DescriptionAttr<T>(this T source)
{
FieldInfo fi = source.GetType().GetField(source.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0) return attributes[0].Description;
else return source.ToString();
}
public static int Port { get; set; } = 5000;
private static readonly TimeSpan TIMEOUT_DEFAULT = TimeSpan.FromSeconds(30);
public static TimeSpan Timeout { get; set; } = TIMEOUT_DEFAULT;
public static Protocol Protocol { get; set; } = Protocol.http;
/// <summary>
///
/// </summary>
/// <param name="host">device ip address or host name</param>
/// <param name="command"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static async Task<string> GetResourceAsync(string host, CommandName command, CancellationToken cancellationToken)
{
VerifyHost(host);
try
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = Timeout;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
var response = await httpClient.GetAsync(requestUri, cancellationToken);
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
{
var errorJson = await response.Content.ReadAsStringAsync();
var res = JsonConvert.DeserializeObject<ErrorMessage>(errorJson);
throw new CanApiException(res.Error, 500);
}
response.EnsureSuccessStatusCode();
}
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
public static async Task<string> PostResourceAsync<T>(string host, CommandName command, T request, CancellationToken cancellationToken)
{
VerifyHost(host);
try
{
HttpResponseMessage response = await PostAsJsonAsync(host, command, request, Timeout, cancellationToken);
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
public static async Task<Stream> SendResourceReadAsStreamAsync<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
VerifyHost(host);
return await SendResourceReadAsStreamProcess(host, command, request, timeOut, cancellationToken);
}
private static async Task<Stream> SendResourceReadAsStreamProcess<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
try
{
HttpResponseMessage response = await SendAsync(host, command, request, timeOut, cancellationToken);
return await response.Content.ReadAsStreamAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
private static void VerifyHost(string host)
{
if (string.IsNullOrEmpty(host)) { throw new ArgumentNullException("host", "host cannot be empty"); }
}
public static async Task<string> PostResourceReadAsStringAsync(string host, CommandName command, MultipartFormDataContent multipart, TimeSpan timeOut, CancellationToken cancellationToken)
{
VerifyHost(host);
try
{
var response = await PostWithMultipartFormAsync(host, command, multipart, timeOut, cancellationToken);
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
private static async Task<HttpResponseMessage> PostAsJsonAsync<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = timeOut;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
var response = await httpClient.PostAsJsonAsync(requestUri, request, cancellationToken);
await ValidateResponse(response);
return response;
}
private static async Task<HttpResponseMessage> PostWithMultipartFormAsync(string host, CommandName command, MultipartFormDataContent multipart, TimeSpan timeOut, CancellationToken cancellationToken)
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = timeOut;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
var response = await httpClient.PostAsync(requestUri, multipart, cancellationToken);
await ValidateResponse(response);
return response;
}
private static async Task<HttpResponseMessage> SendAsync<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = timeOut;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri);
var json = JsonConvert.SerializeObject(request);
var content = new StringContent(json, Encoding.UTF8, "application/json");
httpRequestMessage.Content = content;
var response = await httpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
await ValidateResponse(response);
return response;
}
private static async Task<ErrorMessage> BuildErrorMessage(HttpResponseMessage response)
{
var errorJson = await response.Content.ReadAsStringAsync();
var res = JsonConvert.DeserializeObject<ErrorMessage>(errorJson);
return res;
}
private static async Task ValidateResponse(HttpResponseMessage response)
{
if (!response.IsSuccessStatusCode)
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.BadRequest:
throw new CanApiException((await BuildErrorMessage(response)).Error, 400);
case System.Net.HttpStatusCode.Forbidden:
throw new CanApiException((await BuildErrorMessage(response)).Error, 403);
case System.Net.HttpStatusCode.NotFound:
throw new CanApiException((await BuildErrorMessage(response)).Error, 404);
case System.Net.HttpStatusCode.InternalServerError:
throw new CanApiException((await BuildErrorMessage(response)).Error, 500);
case System.Net.HttpStatusCode.ServiceUnavailable:
throw new CanApiException((await BuildErrorMessage(response)).Error, 503);
}
response.EnsureSuccessStatusCode();
}
}
public static async Task WriteStreamToFileAsync(Stream inputStream, string filePath)
{
if (inputStream.CanSeek)
{
inputStream.Position = 0;
}
using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
await inputStream.CopyToAsync(fileStream);
}
}
}
}

View File

@@ -0,0 +1,15 @@
namespace CANFDApiProxy.Messages
{
public class BatteryMessage
{
public decimal LoadV { get; set; }
public decimal Current { get; set; }
public decimal Power { get; set; }
public decimal Percent { get; set; }
public bool Enable { get; set; }
public override string ToString()
{
return $"LoadV: {LoadV}, Current: {Current}, Power: {Power}, Percent: {Percent}, Enable: {Enable}";
}
}
}

View File

@@ -0,0 +1,11 @@
namespace CANFDApiProxy.Messages
{
public class DiagnosticsMessageRequest
{
public string format { get; set; }
public override string ToString()
{
return $"format: {format}";
}
}
}

View File

@@ -0,0 +1,27 @@
using CANFDApiProxy.Messages;
namespace CANFDApiProxy.Requests
{
public class CANConfigRequest
{
public config config { get; set; }
public string Status { get; set; }
public override string ToString()
{
return $"config: {config}, Status: {Status}";
}
}
public class config
{
public CanConfigItem can1 { get; set; }
public CanConfigItem can2 { get; set; }
public CanConfigItem can3 { get; set; }
public CanConfigItem can4 { get; set; }
public override string ToString()
{
return $"can1: {can1}, can2: {can2}, can3: {can3}, can4: {can4}";
}
}
}

View File

@@ -0,0 +1,226 @@
using CANFDApiProxy.Messages;
using Newtonsoft.Json;
using System;
using System.CodeDom;
using System.ComponentModel;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CANFDApiProxy
{
internal static class RESTWrapper
{
/// <summary>
/// Get the description part of the enum
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <returns></returns>
private static string DescriptionAttr<T>(this T source)
{
FieldInfo fi = source.GetType().GetField(source.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0) return attributes[0].Description;
else return source.ToString();
}
public static int Port { get; set; } = 5000;
private static readonly TimeSpan TIMEOUT_DEFAULT = new TimeSpan(0, 0, 10);
public static TimeSpan Timeout { get; set; } = TIMEOUT_DEFAULT;
public static Protocol Protocol { get; set; } = Protocol.http;
/// <summary>
///
/// </summary>
/// <param name="host">device ip address or host name</param>
/// <param name="command"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static async Task<string> GetResourceAsync(string host, CommandName command, CancellationToken cancellationToken)
{
VerifyHost(host);
try
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = Timeout;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
var response = await httpClient.GetAsync(requestUri, cancellationToken);
if (!response.IsSuccessStatusCode)
{
if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
{
var errorJson = await response.Content.ReadAsStringAsync();
var res = JsonConvert.DeserializeObject<ErrorMessage>(errorJson);
throw new CanApiException(res.Error, 500);
}
response.EnsureSuccessStatusCode();
}
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
public static async Task<string> PostResourceAsync<T>(string host, CommandName command, T request, CancellationToken cancellationToken)
{
VerifyHost(host);
try
{
HttpResponseMessage response = await PostAsJsonAsync(host, command, request, Timeout, cancellationToken);
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
public static async Task<Stream> SendResourceReadAsStreamAsync<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
VerifyHost(host);
return await SendResourceReadAsStreamProcess(host, command, request, timeOut, cancellationToken);
}
private static async Task<Stream> SendResourceReadAsStreamProcess<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
try
{
HttpResponseMessage response = await SendAsync(host, command, request, timeOut, cancellationToken);
return await response.Content.ReadAsStreamAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
private static void VerifyHost(string host)
{
if (string.IsNullOrEmpty(host)) { throw new ArgumentNullException("host", "host cannot be empty"); }
}
public static async Task<string> PostResourceReadAsStringAsync(string host, CommandName command, MultipartFormDataContent multipart, TimeSpan timeOut, CancellationToken cancellationToken)
{
VerifyHost(host);
try
{
var response = await PostWithMultipartFormAsync(host, command, multipart, timeOut, cancellationToken);
return await response.Content.ReadAsStringAsync();
}
catch (TaskCanceledException ex)
{
throw new CanApiException("An API call was cancelled or timedout", ex);
}
}
private static async Task<HttpResponseMessage> PostAsJsonAsync<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = timeOut;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
var response = await httpClient.PostAsJsonAsync(requestUri, request, cancellationToken);
await ValidateResponse(response);
return response;
}
private static async Task<HttpResponseMessage> PostWithMultipartFormAsync(string host, CommandName command, MultipartFormDataContent multipart, TimeSpan timeOut, CancellationToken cancellationToken)
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = timeOut;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
var response = await httpClient.PostAsync(requestUri, multipart, cancellationToken);
await ValidateResponse(response);
return response;
}
private static async Task<HttpResponseMessage> SendAsync<T>(string host, CommandName command, T request, TimeSpan timeOut, CancellationToken cancellationToken)
{
var httpClient = HttpClientFactory.CreateHttpClient();
httpClient.Timeout = timeOut;
var commandString = command.DescriptionAttr();
string requestUri = $"{Protocol.ToString()}://{host}:{Port}/{commandString}";
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri);
var json = JsonConvert.SerializeObject(request);
var content = new StringContent(json, Encoding.UTF8, "application/json");
httpRequestMessage.Content = content;
var response = await httpClient.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
await ValidateResponse(response);
return response;
}
private static async Task<ErrorMessage> BuildErrorMessage(HttpResponseMessage response)
{
var errorJson = await response.Content.ReadAsStringAsync();
var res = JsonConvert.DeserializeObject<ErrorMessage>(errorJson);
return res;
}
private static async Task ValidateResponse(HttpResponseMessage response)
{
if (!response.IsSuccessStatusCode)
{
switch (response.StatusCode)
{
case System.Net.HttpStatusCode.BadRequest:
throw new CanApiException((await BuildErrorMessage(response)).Error, 400);
case System.Net.HttpStatusCode.Forbidden:
throw new CanApiException((await BuildErrorMessage(response)).Error, 403);
case System.Net.HttpStatusCode.NotFound:
throw new CanApiException((await BuildErrorMessage(response)).Error, 404);
case System.Net.HttpStatusCode.InternalServerError:
throw new CanApiException((await BuildErrorMessage(response)).Error, 500);
case System.Net.HttpStatusCode.ServiceUnavailable:
throw new CanApiException((await BuildErrorMessage(response)).Error, 503);
}
response.EnsureSuccessStatusCode();
}
}
public static async Task WriteStreamToFileAsync(Stream inputStream, string filePath)
{
if (inputStream.CanSeek)
{
inputStream.Position = 0;
}
using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
await inputStream.CopyToAsync(fileStream);
}
}
}
}

View File

@@ -0,0 +1,11 @@
namespace CANFDApiProxy.Messages
{
public class BatteryMessage
{
public decimal LoadV { get; set; }
public decimal Current { get; set; }
public decimal Power { get; set; }
public decimal Percent { get; set; }
public bool Enable { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace CANFDApiProxy.Messages
{
public class StatusMessage
{
public string status { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
namespace CANFDApiProxy.Requests
{
public class LEDsRequest
{
public string led { get; set; }
public string cmd { get; set; }
public string color { get; set; }
}
public enum LedColor
{
red,
green,
blue
}
public enum LedCmd
{
on,
off,
}
public enum LedName
{
can1, can2, can3, can4, pwr, sts, status
}
}

View File

@@ -0,0 +1,507 @@
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;
}
}
}

View File

@@ -0,0 +1,141 @@
namespace CANFDApiProxy.Messages
{
internal class CANInfoInternal
{
public Can1 can1 { get; set; }
public Can2 can2 { get; set; }
public Can3 can3 { get; set; }
public Can4 can4 { get; set; }
public Pipe pipe { get; set; }
public Battery battery { get; set; }
public Pwr pwr { get; set; }
public Status status { get; set; }
public Sts sts { get; set; }
}
internal class Can1
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
internal class Can2
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
internal class Can3
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
internal class Can4
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
public class Pipe
{
public string path { get; set; }
}
public class Pwr
{
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
public class Status
{
public bool pin { get; set; }
}
public class Sts
{
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
public class Battery
{
public bool enable { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Messages
{
public class SerialMessage
{
public string Serial { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANInfoMessage
{
public List<CANInfo> CANInfoList { get; set; }
}
public class CANInfo
{
public CANInfo(string name, string info)
{
Name = name;
Info = info;
}
public string Name { get; }
public string Info { get; }
}
}

View File

@@ -0,0 +1,9 @@
namespace CANFDApiProxy.Requests
{
public class NetworkRequest
{
public bool dhcp { get; set; }
public string set_address { get; set; }
}
}

View File

@@ -0,0 +1,77 @@
using CANFDApiProxy.Requests;
using System;
using System.Collections.Generic;
using System.Text;
namespace CANFDApiProxy.Messages
{
public class CANConfigMessage
{
public List<CANConfig> CANConfigList { get; set; }
public Pipe Pipe { get; set; }
public string Status { get; set; }
public static CANConfigRequest CreateCanConfigRequest(CANConfigMessage canConfigMessage)
{
var request = new CANConfigRequest();
try
{
request.config = new config();
var CANConfigArray = canConfigMessage.CANConfigList.ToArray();
request.config.can1 = new CanConfigItem(CANConfigArray[0].Base_or_arb_bitrate, CANConfigArray[0].Base_or_arb_sjw, CANConfigArray[0].Data_bitrate, CANConfigArray[0].Data_sjw, CANConfigArray[0].Filetype, CANConfigArray[0].Included, CANConfigArray[0].Is_fd);
request.config.can2 = new CanConfigItem(CANConfigArray[1].Base_or_arb_bitrate, CANConfigArray[1].Base_or_arb_sjw, CANConfigArray[1].Data_bitrate, CANConfigArray[1].Data_sjw, CANConfigArray[1].Filetype, CANConfigArray[1].Included, CANConfigArray[1].Is_fd);
request.config.can3 = new CanConfigItem(CANConfigArray[2].Base_or_arb_bitrate, CANConfigArray[2].Base_or_arb_sjw, CANConfigArray[2].Data_bitrate, CANConfigArray[2].Data_sjw, CANConfigArray[2].Filetype, CANConfigArray[2].Included, CANConfigArray[2].Is_fd);
request.config.can4 = new CanConfigItem(CANConfigArray[3].Base_or_arb_bitrate, CANConfigArray[3].Base_or_arb_sjw, CANConfigArray[3].Data_bitrate, CANConfigArray[3].Data_sjw, CANConfigArray[3].Filetype, CANConfigArray[3].Included, CANConfigArray[3].Is_fd);
}
catch (Exception ex)
{
request.Status = ex.Message;
}
return request;
}
public override string ToString()
{
var sb = new StringBuilder();
sb.Append($"Pipe: {Pipe}, Status: {Status}, CanConfigList:");
if (null != CANConfigList)
{
foreach( var c in CANConfigList)
{
sb.Append(" ");
sb.Append(c.ToString());
}
}
return sb.ToString();
}
}
public class CANConfig
{
public CANConfig(string name, int base_or_arb_bitrate, int base_or_arb_sjw, int data_bitrate, int data_sjw, string filetype, bool included, bool is_fd)
{
Name = name;
Base_or_arb_bitrate = base_or_arb_bitrate;
Base_or_arb_sjw = base_or_arb_sjw;
Data_bitrate = data_bitrate;
Data_sjw = data_sjw;
Filetype = filetype;
Included = included;
Is_fd = is_fd;
}
public string Name { get; }
public int Base_or_arb_bitrate { get; set; }
public int Base_or_arb_sjw { get; set; }
public int Data_bitrate { get; set; }
public int Data_sjw { get; set; }
public string Filetype { get; set; }
public bool Included { get; set; }
public bool Is_fd { get; set; }
public override string ToString()
{
return $"Name={Name}, BaseBR={Base_or_arb_bitrate}, BaseSJW={Base_or_arb_sjw}, BR={Data_bitrate}, DataSJW={Data_sjw}, FT={Filetype}, Inc={Included}, fd={Is_fd}";
}
}
}

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0A42EE20-660C-468D-9511-C32C9037CB15}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CANFDApiProxy</RootNamespace>
<AssemblyName>CANFDApiProxy</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.DependencyInjection.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Http, Version=9.0.0.10, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Http.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Options, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Options.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Primitives.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Windows.Shell">
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Windows.Shell.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json.Bson">
<HintPath>..\..\Common\DTS.Common\lib\Newtonsoft.Json.Bson.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CanApiException.cs" />
<Compile Include="CANFD.cs" />
<Compile Include="CommandName.cs" />
<Compile Include="Messages\CANConfigMessage.cs" />
<Compile Include="Messages\CANInfoInternal.cs" />
<Compile Include="Messages\CANInfoMessage.cs" />
<Compile Include="Messages\CANStateMessage.cs" />
<Compile Include="Messages\CANStatsMessage.cs" />
<Compile Include="Messages\ClocksMessage.cs" />
<Compile Include="Messages\DeviceInfoMessage.cs" />
<Compile Include="Messages\EventPinMessage.cs" />
<Compile Include="Messages\LEDsPostMessage.cs" />
<Compile Include="Messages\NetworkMessage.cs" />
<Compile Include="Messages\NtpMessage.cs" />
<Compile Include="Messages\PowerMessage.cs" />
<Compile Include="Messages\RecordingMessage.cs" />
<Compile Include="Messages\ServicesMessage.cs" />
<Compile Include="Messages\StatusMessage.cs" />
<Compile Include="Messages\UsbStatsMessage.cs" />
<Compile Include="Messages\ErrorMessage.cs" />
<Compile Include="Messages\UsbTreeMessage.cs" />
<Compile Include="Requests\CanConfigItem.cs" />
<Compile Include="Requests\CANConfigRequest.cs" />
<Compile Include="Requests\CanPostRequest.cs" />
<Compile Include="Requests\ClocksRequest.cs" />
<Compile Include="Requests\FileRequest.cs" />
<Compile Include="Requests\LEDsRequest.cs" />
<Compile Include="Requests\NetworkRequest.cs" />
<Compile Include="Requests\SerialRequest.cs" />
<Compile Include="Protocol.cs" />
<Compile Include="RESTWrapper.cs" />
<Compile Include="HttpClientFactory.cs" />
<Compile Include="Interfaces\ICANFDApi.cs" />
<Compile Include="Messages\BatteryMessage.cs" />
<Compile Include="Messages\LEDsMessage.cs" />
<Compile Include="Messages\SerialMessage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,16 @@
namespace CANFDApiProxy.Messages
{
public class PowerMessage
{
public bool Battery_enable { get; set; }
public bool Nvin_pin { get; set; }
public bool On_pin { get; set; }
public bool Power_fault { get; set; }
public string Status { get; set; }
public override string ToString()
{
return $"Battery_enable: {Battery_enable}, Nvin_pin: {Nvin_pin}, On_pin: {On_pin}, Power_fault: {Power_fault}, Status: {Status}";
}
}
}

View File

@@ -0,0 +1,18 @@
namespace CANFDApiProxy.Messages
{
public class UsbTreeMessage
{
public Child[] children { get; set; }
public string name { get; set; }
public string path { get; set; }
public string type { get; set; }
}
public class Child
{
public Child[] children { get; set; }
public string name { get; set; }
public string path { get; set; }
public string type { get; set; }
}
}

View File

@@ -0,0 +1,470 @@
using CANFDApiProxy.Interfaces;
using CANFDApiProxy.Messages;
using CANFDApiProxy.Requests;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
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;
}
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> 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;
}
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy
{
public enum Protocol
{
http,
https
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CANFDApiProxy
{
public class CanApiException : Exception
{
public int? StatusCode { get; set; }
public CanApiException(string message, Exception inner) : base(message, inner)
{
}
public CanApiException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
}
}

View File

@@ -0,0 +1,19 @@
using CANFDApiProxy.Messages;
namespace CANFDApiProxy.Requests
{
public class CANConfigRequest
{
public config config { get; set; }
public string Status { get; set; }
}
public class config
{
public CanConfigItem can1 { get; set; }
public CanConfigItem can2 { get; set; }
public CanConfigItem can3 { get; set; }
public CanConfigItem can4 { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANStatsMessage
{
public List<CANStats> CANStatsList { get; set; }
}
public class CANStats
{
public CANStats(string name, int std_data, int std_remote, int ext_data, int ext_remote, int err_frame, float bus_load
, int overruns, float last_updated)
{
Name = name;
Last_updated = last_updated;
Std_data = std_data;
Std_remote = std_remote;
Ext_remote = ext_remote;
Err_frame = err_frame;
Bus_load = bus_load;
Ext_data = ext_data;
Overruns = overruns;
}
public string Name { get; }
public float Last_updated { get; set; }
public int Std_data { get; set; }
public int Std_remote { get; set; }
public int Ext_data { get; set; }
public int Ext_remote { get; set; }
public int Err_frame { get; set; }
public float Bus_load { get; set; }
public int Overruns { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace CANFDApiProxy.Messages
{
public class RecordingMessage
{
public string Recording { get; set; }
public bool Autoarm { get; set; }
public string Recording_dir { get; set; }
public string Ok { get; set; }
public string Reply { get; set; }
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Messages
{
public class ErrorMessage
{
public string Error { get; set; }
}
}

View File

@@ -0,0 +1,57 @@
using CANFDApiProxy.Requests;
using System;
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANConfigMessage
{
public List<CANConfig> CANConfigList { get; set; }
public Pipe Pipe { get; set; }
public string Status { get; set; }
public static CANConfigRequest CreateCanConfigRequest(CANConfigMessage canConfigMessage)
{
var request = new CANConfigRequest();
try
{
request.config = new config();
var CANConfigArray = canConfigMessage.CANConfigList.ToArray();
request.config.can1 = new CanConfigItem(CANConfigArray[0].Base_or_arb_bitrate, CANConfigArray[0].Base_or_arb_sjw, CANConfigArray[0].Data_bitrate, CANConfigArray[0].Data_sjw, CANConfigArray[0].Filetype, CANConfigArray[0].Included, CANConfigArray[0].Is_fd);
request.config.can2 = new CanConfigItem(CANConfigArray[1].Base_or_arb_bitrate, CANConfigArray[1].Base_or_arb_sjw, CANConfigArray[1].Data_bitrate, CANConfigArray[1].Data_sjw, CANConfigArray[1].Filetype, CANConfigArray[1].Included, CANConfigArray[1].Is_fd);
request.config.can3 = new CanConfigItem(CANConfigArray[2].Base_or_arb_bitrate, CANConfigArray[2].Base_or_arb_sjw, CANConfigArray[2].Data_bitrate, CANConfigArray[2].Data_sjw, CANConfigArray[2].Filetype, CANConfigArray[2].Included, CANConfigArray[2].Is_fd);
request.config.can4 = new CanConfigItem(CANConfigArray[3].Base_or_arb_bitrate, CANConfigArray[3].Base_or_arb_sjw, CANConfigArray[3].Data_bitrate, CANConfigArray[3].Data_sjw, CANConfigArray[3].Filetype, CANConfigArray[3].Included, CANConfigArray[3].Is_fd);
}
catch (Exception ex)
{
request.Status = ex.Message;
}
return request;
}
}
public class CANConfig
{
public CANConfig(string name, int base_or_arb_bitrate, int base_or_arb_sjw, int data_bitrate, int data_sjw, string filetype, bool included, bool is_fd)
{
Name = name;
Base_or_arb_bitrate = base_or_arb_bitrate;
Base_or_arb_sjw = base_or_arb_sjw;
Data_bitrate = data_bitrate;
Data_sjw = data_sjw;
Filetype = filetype;
Included = included;
Is_fd = is_fd;
}
public string Name { get; }
public int Base_or_arb_bitrate { get; set; }
public int Base_or_arb_sjw { get; set; }
public int Data_bitrate { get; set; }
public int Data_sjw { get; set; }
public string Filetype { get; set; }
public bool Included { get; set; }
public bool Is_fd { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace CANFDApiProxy.Requests
{
public class SerialRequest
{
public string serial { get; set; }
}
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0A42EE20-660C-468D-9511-C32C9037CB15}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CANFDApiProxy</RootNamespace>
<AssemblyName>CANFDApiProxy</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="CsvHelper">
<HintPath>..\..\Common\DTS.Common\lib\CsvHelper33.0.1\CsvHelper.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.DependencyInjection.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Http, Version=9.0.0.10, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Http.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Options, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Options.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Primitives.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Windows.Shell">
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Windows.Shell.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json.Bson">
<HintPath>..\..\Common\DTS.Common\lib\Newtonsoft.Json.Bson.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CanApiException.cs" />
<Compile Include="CANFD.cs" />
<Compile Include="CommandName.cs" />
<Compile Include="Messages\CANConfigMessage.cs" />
<Compile Include="Messages\CANInfoInternal.cs" />
<Compile Include="Messages\CANInfoMessage.cs" />
<Compile Include="Messages\CANStateMessage.cs" />
<Compile Include="Messages\CANStatsMessage.cs" />
<Compile Include="Messages\ClocksMessage.cs" />
<Compile Include="Messages\DeviceInfoMessage.cs" />
<Compile Include="Messages\DiagnosticsMessage.cs" />
<Compile Include="Messages\EventPinMessage.cs" />
<Compile Include="Messages\LEDsPostMessage.cs" />
<Compile Include="Messages\NetworkMessage.cs" />
<Compile Include="Messages\NtpMessage.cs" />
<Compile Include="Messages\PowerMessage.cs" />
<Compile Include="Messages\RecordingMessage.cs" />
<Compile Include="Messages\CalibrationMessage.cs" />
<Compile Include="Messages\ServicesMessage.cs" />
<Compile Include="Messages\StatusMessage.cs" />
<Compile Include="Messages\UsbStatsMessage.cs" />
<Compile Include="Messages\ErrorMessage.cs" />
<Compile Include="Messages\UsbTreeMessage.cs" />
<Compile Include="Requests\CanConfigItem.cs" />
<Compile Include="Requests\CANConfigRequest.cs" />
<Compile Include="Requests\CanPostRequest.cs" />
<Compile Include="Requests\ClocksRequest.cs" />
<Compile Include="Requests\FileRequest.cs" />
<Compile Include="Requests\LEDsRequest.cs" />
<Compile Include="Requests\NetworkRequest.cs" />
<Compile Include="Requests\SerialRequest.cs" />
<Compile Include="Protocol.cs" />
<Compile Include="RESTWrapper.cs" />
<Compile Include="HttpClientFactory.cs" />
<Compile Include="Interfaces\ICANFDApi.cs" />
<Compile Include="Messages\BatteryMessage.cs" />
<Compile Include="Messages\LEDsMessage.cs" />
<Compile Include="Messages\SerialMessage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,16 @@
namespace CANFDApiProxy.Messages
{
public class EventPinMessage
{
public bool? Armed { get; set; }
public bool? Event { get; set; }
public bool? Event_pin { get; set; }
public string File_name { get; set; }
public string Ok { get; set; }
public string Reply { get; set; }
public override string ToString()
{
return $"Armed: {Armed}, Event: {Event}, Event_pin: {Event_pin}, File_name: {File_name}, Ok: {Ok}, Reply: {Reply}";
}
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class CalibrationMessage
{
public int Calibration_date { get; set; }
public string Calibration_date_string { get; set; }
public override string ToString()
{
return $"Calibration_date: {Calibration_date}, Calibration_date_string: {Calibration_date_string}";
}
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class SerialMessage
{
public string Serial { get; set; }
public string Status { get; set; }
public override string ToString()
{
return $"Serial={Serial}, Status={Status}";
}
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class PowerMessage
{
public bool Battery_enable { get; set; }
public bool Nvin_pin { get; set; }
public bool On_pin { get; set; }
public bool Power_fault { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
namespace CANFDApiProxy.Requests
{
public class CanConfigItem
{
public CanConfigItem(int base_or_arb_bitrate, int base_or_arb_sjw, int data_bitrate, int data_sjw, string filetype, bool included, bool is_fd)
{
this.base_or_arb_bitrate = base_or_arb_bitrate;
this.base_or_arb_sjw = base_or_arb_sjw;
this.data_bitrate = data_bitrate;
this.data_sjw = data_sjw;
this.filetype = filetype;
this.included = included;
this.is_fd = is_fd;
}
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public override string ToString()
{
return $"baseBR: {base_or_arb_bitrate}, baseSJW: {base_or_arb_sjw}, br: {data_bitrate}, sjw: {data_sjw}, ft: {filetype}, inc: {included}, fd: {is_fd}";
}
}
}

View File

@@ -0,0 +1,7 @@
namespace CANFDApiProxy.Requests
{
internal class CanPostRequest
{
public string cmd { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace CANFDApiProxy.Messages
{
public class ServicesMessage
{
public Service[] services { get; set; }
}
public class Service
{
public bool Enabled { get; set; }
public string Name { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CANFDApiProxy")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("VPG")]
[assembly: AssemblyProduct("CANFDApiProxy")]
[assembly: AssemblyCopyright("Copyright © VPG 2025")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("0a42ee20-660c-468d-9511-c32c9037cb15")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,10 @@
namespace CANFDApiProxy.Messages
{
public class NtpMessage
{
public string Ntp { get; set; }
public string Fallback { get; set; }
}
}

View File

@@ -0,0 +1,48 @@
using System.ComponentModel;
namespace CANFDApiProxy
{
internal enum CommandName
{
[Description("serial")]
Serial,
[Description("leds")]
LEDs,
[Description("battery")]
Battery,
[Description("calibration-date")]
CalibrationDate,
[Description("can-info")]
CANInfo,
[Description("can-state")]
CANState,
[Description("can-stats")]
CANStats,
[Description("can-config")]
CANConfig,
[Description("device-info")]
DeviceInfo,
[Description("ntp")]
Ntp,
[Description("power")]
Power,
[Description("services")]
Services,
[Description("network")]
Network,
[Description("clocks")]
Clocks,
[Description("event-pin")]
EventPin,
[Description("recording")]
Recording,
[Description("usb-stats")]
UsbStats,
[Description("usb-tree")]
UsbTree,
[Description("file")]
File,
[Description("diagnostics")]
Diagnostics
}
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANStateMessage
{
public List<CANState> CANStateList { get; set; }
}
public class CANState
{
public CANState(string name, string state, float last_updated)
{
Name = name;
State = state;
Last_updated = last_updated;
}
public string Name { get; }
public string State { get; set; }
public float Last_updated { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
namespace CANFDApiProxy.Messages
{
public class RecordingMessage
{
public string Recording { get; set; }
public bool Autoarm { get; set; }
public string Recording_dir { get; set; }
public string Ok { get; set; }
public string Reply { get; set; }
public override string ToString()
{
return $"Recording: {Recording}, AutoArm: {Autoarm}, Recording_dir{Recording_dir}, Ok: {Ok}, Reply: {Reply}";
}
}
}

View File

@@ -0,0 +1,10 @@
namespace CANFDApiProxy.Messages
{
public class ClocksMessage
{
public bool? Rtc_present { get; set; }
public bool? Rtc_setup { get; set; }
public string System { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class LEDsMessage
{
public List<LED> LEDs { get; set; }
public Battery Battery { get; set; }
public Pwr Pwr { get; set; }
public Status Status { get; set; }
public Sts Sts { get; set; }
}
public class LED
{
public LED(string name, bool blue, bool green, bool red)
{
Name = name;
Blue = blue;
Green = green;
Red = red;
}
public string Name { get; }
public bool Red { get; }
public bool Green { get; }
public bool Blue { get; }
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class NetworkMessage
{
public string Current_address { get; set; }
public bool Dhcp { get; set; }
public string Interface { get; set; }
public string Mac_address { get; set; }
public string Set_address { get; set; }
public string Ok { get; set; }
}
}

Binary file not shown.

View File

View File

@@ -0,0 +1,507 @@
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;
}
}
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0A42EE20-660C-468D-9511-C32C9037CB15}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CANFDApiProxy</RootNamespace>
<AssemblyName>CANFDApiProxy</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="CsvHelper">
<HintPath>..\..\Common\DTS.Common\lib\CsvHelper33.0.1\CsvHelper.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.DependencyInjection.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Http, Version=9.0.0.10, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Http.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Logging.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Options, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Options.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Primitives, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Extensions.Primitives.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Windows.Shell">
<HintPath>..\..\Common\DTS.Common\lib\Microsoft.Windows.Shell.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json.Bson">
<HintPath>..\..\Common\DTS.Common\lib\Newtonsoft.Json.Bson.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.7.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\Common\DTS.Common\lib\HttpClientFactory\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CanApiException.cs" />
<Compile Include="CANFD.cs" />
<Compile Include="CommandName.cs" />
<Compile Include="Messages\CANConfigMessage.cs" />
<Compile Include="Messages\CANInfoInternal.cs" />
<Compile Include="Messages\CANInfoMessage.cs" />
<Compile Include="Messages\CANStateMessage.cs" />
<Compile Include="Messages\CANStatsMessage.cs" />
<Compile Include="Messages\ClocksMessage.cs" />
<Compile Include="Messages\DeviceInfoMessage.cs" />
<Compile Include="Messages\DiagnosticsMessage.cs" />
<Compile Include="Messages\EventPinMessage.cs" />
<Compile Include="Messages\LEDsPostMessage.cs" />
<Compile Include="Messages\NetworkMessage.cs" />
<Compile Include="Messages\NtpMessage.cs" />
<Compile Include="Messages\PowerMessage.cs" />
<Compile Include="Messages\RecordingMessage.cs" />
<Compile Include="Messages\CalibrationMessage.cs" />
<Compile Include="Messages\ServicesMessage.cs" />
<Compile Include="Messages\StatusMessage.cs" />
<Compile Include="Messages\UsbStatsMessage.cs" />
<Compile Include="Messages\ErrorMessage.cs" />
<Compile Include="Messages\UsbTreeMessage.cs" />
<Compile Include="Requests\CanConfigItem.cs" />
<Compile Include="Requests\CANConfigRequest.cs" />
<Compile Include="Requests\CanPostRequest.cs" />
<Compile Include="Requests\ClocksRequest.cs" />
<Compile Include="Requests\FileRequest.cs" />
<Compile Include="Requests\LEDsRequest.cs" />
<Compile Include="Requests\NetworkRequest.cs" />
<Compile Include="Requests\SerialRequest.cs" />
<Compile Include="Protocol.cs" />
<Compile Include="RESTWrapper.cs" />
<Compile Include="HttpClientFactory.cs" />
<Compile Include="Interfaces\ICANFDApi.cs" />
<Compile Include="Messages\BatteryMessage.cs" />
<Compile Include="Messages\LEDsMessage.cs" />
<Compile Include="Messages\SerialMessage.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\DTS.Common\DTS.Common.csproj">
<Project>{f7a0804f-61a4-40ae-83d0-f1137622b592}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CANFDApiProxy
{
public class CanApiException : Exception
{
public int? StatusCode { get; set; }
public CanApiException(string message, Exception inner) : base(message, inner)
{
}
public CanApiException(string message, int statusCode) : base(message)
{
StatusCode = statusCode;
}
}
}

View File

@@ -0,0 +1,48 @@
using System.ComponentModel;
namespace CANFDApiProxy
{
internal enum CommandName
{
[Description("serial")]
Serial,
[Description("leds")]
LEDs,
[Description("battery")]
Battery,
[Description("calibration-date")]
CalibrationDate,
[Description("can-info")]
CANInfo,
[Description("can-state")]
CANState,
[Description("can-stats")]
CANStats,
[Description("can-config")]
CANConfig,
[Description("device-info")]
DeviceInfo,
[Description("ntp")]
Ntp,
[Description("power")]
Power,
[Description("services")]
Services,
[Description("network")]
Network,
[Description("clocks")]
Clocks,
[Description("event-pin")]
EventPin,
[Description("recording")]
Recording,
[Description("usb-stats")]
UsbStats,
[Description("usb-tree")]
UsbTree,
[Description("file")]
File,
[Description("diagnostics")]
Diagnostics
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http;
namespace CANFDApiProxy
{
public static class HttpClientFactory
{
private static IHttpClientFactory CreateHttpClientFactory()
{
var httpClientFactory = new ServiceCollection().AddHttpClient().BuildServiceProvider().GetRequiredService<IHttpClientFactory>();
return httpClientFactory;
}
public static HttpClient CreateHttpClient()
{
IHttpClientFactory httpClientFactory = CreateHttpClientFactory();
var httpClient = httpClientFactory.CreateClient();
httpClient.DefaultRequestHeaders.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
return httpClient;
}
}
}

View File

@@ -0,0 +1,46 @@
using CANFDApiProxy.Messages;
using CANFDApiProxy.Requests;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace CANFDApiProxy.Interfaces
{
public interface ICANFDApi
{
Task<UsbTreeMessage> GetUsbTree(string deviceHost, CancellationToken cancellationToken);
Task<UsbStatsMessage> GetUsbStats(string deviceHost, CancellationToken cancellationToken);
Task<SerialMessage> GetSerial(string deviceHost, CancellationToken cancellationToken);
Task<LEDsMessage> GetLEDs(string deviceHost, CancellationToken cancellationToken);
Task<ClocksMessage> GetClocks(string deviceHost, CancellationToken cancellationToken);
Task<EventPinMessage> GetEventPin(string deviceHost, CancellationToken cancellationToken);
Task<CANConfigMessage> GetCANConfig(string deviceHost, CancellationToken cancellationToken);
Task<CANInfoMessage> GetCANInfo(string deviceHost, CancellationToken cancellationToken);
Task<CANStateMessage> GetCANState(string deviceHost, CancellationToken cancellationToken);
Task<CANStatsMessage> GetCANStats(string deviceHost, CancellationToken cancellationToken);
Task<BatteryMessage> GetBattery(string deviceHost, CancellationToken cancellationToken);
Task<ServicesMessage> GetServices(string deviceHost, CancellationToken cancellationToken);
Task<NtpMessage> GetNtp(string deviceHost, CancellationToken cancellationToken);
Task<PowerMessage> GetPower(string deviceHost, CancellationToken cancellationToken);
Task<DeviceInfoMessage> GetDeviceInfo(string deviceHost, CancellationToken cancellationToken);
Task<RecordingMessage> GetRecording(string deviceHost, CancellationToken cancellationToken);
Task<NetworkMessage> GetNetwork(string deviceHost, CancellationToken cancellationToken);
Task<SerialMessage> SetSerial(string deviceHost, SerialRequest serialRequest, CancellationToken cancellationToken);
Task<LEDsPostMessage> SetLEDs(string deviceHost, LedName led, LedCmd cmd, LedColor color, CancellationToken cancellationToken);
Task<ClocksMessage> SetClocks(string deviceHost,DateTime dateTime, CancellationToken cancellationToken);
Task<EventPinMessage> SetEventPinArm(string deviceHost, CancellationToken cancellationToken);
Task<EventPinMessage> SetEventPinDisarm(string deviceHost, CancellationToken cancellationToken);
Task<ClocksMessage> SyncClocks(string deviceHost, CancellationToken cancellationToken);
Task<CANConfigMessage> SetCANConfig(string deviceHost, CANConfigRequest canConfigRequest, CancellationToken cancellationToken);
Task<PowerMessage> SetPowerOff(string deviceHost, CancellationToken cancellationToken);
Task<PowerMessage> SetPowerReboot(string deviceHost, CancellationToken cancellationToken);
Task<RecordingMessage> SetRecordingStart(string deviceHost, CancellationToken cancellationToken);
Task<RecordingMessage> SetRecordingStop(string deviceHost, CancellationToken cancellationToken);
Task<NetworkMessage> SetNetwork(string deviceHost, NetworkRequest networkRequest, CancellationToken cancellationToken);
Task Download(string deviceHost, string usbPath, string destinationDirectory, TimeSpan timeOut, CancellationToken cancellationToken);
Task<StatusMessage> Upload(string deviceHost, string uploadUsbPath, string sourcefile, TimeSpan timeOut, CancellationToken cancellationToken);
Task<StatusMessage> Delete(string deviceHost, string usbPath, CancellationToken cancellationToken);
}
}

View File

@@ -0,0 +1,15 @@
namespace CANFDApiProxy.Messages
{
public class BatteryMessage
{
public decimal LoadV { get; set; }
public decimal Current { get; set; }
public decimal Power { get; set; }
public decimal Percent { get; set; }
public bool Enable { get; set; }
public override string ToString()
{
return $"LoadV: {LoadV}, Current: {Current}, Power: {Power}, Percent: {Percent}, Enable: {Enable}";
}
}
}

View File

@@ -0,0 +1,77 @@
using CANFDApiProxy.Requests;
using System;
using System.Collections.Generic;
using System.Text;
namespace CANFDApiProxy.Messages
{
public class CANConfigMessage
{
public List<CANConfig> CANConfigList { get; set; }
public Pipe Pipe { get; set; }
public string Status { get; set; }
public static CANConfigRequest CreateCanConfigRequest(CANConfigMessage canConfigMessage)
{
var request = new CANConfigRequest();
try
{
request.config = new config();
var CANConfigArray = canConfigMessage.CANConfigList.ToArray();
request.config.can1 = new CanConfigItem(CANConfigArray[0].Base_or_arb_bitrate, CANConfigArray[0].Base_or_arb_sjw, CANConfigArray[0].Data_bitrate, CANConfigArray[0].Data_sjw, CANConfigArray[0].Filetype, CANConfigArray[0].Included, CANConfigArray[0].Is_fd);
request.config.can2 = new CanConfigItem(CANConfigArray[1].Base_or_arb_bitrate, CANConfigArray[1].Base_or_arb_sjw, CANConfigArray[1].Data_bitrate, CANConfigArray[1].Data_sjw, CANConfigArray[1].Filetype, CANConfigArray[1].Included, CANConfigArray[1].Is_fd);
request.config.can3 = new CanConfigItem(CANConfigArray[2].Base_or_arb_bitrate, CANConfigArray[2].Base_or_arb_sjw, CANConfigArray[2].Data_bitrate, CANConfigArray[2].Data_sjw, CANConfigArray[2].Filetype, CANConfigArray[2].Included, CANConfigArray[2].Is_fd);
request.config.can4 = new CanConfigItem(CANConfigArray[3].Base_or_arb_bitrate, CANConfigArray[3].Base_or_arb_sjw, CANConfigArray[3].Data_bitrate, CANConfigArray[3].Data_sjw, CANConfigArray[3].Filetype, CANConfigArray[3].Included, CANConfigArray[3].Is_fd);
}
catch (Exception ex)
{
request.Status = ex.Message;
}
return request;
}
public override string ToString()
{
var sb = new StringBuilder();
sb.Append($"Pipe: {Pipe}, Status: {Status}, CanConfigList:");
if (null != CANConfigList)
{
foreach( var c in CANConfigList)
{
sb.Append(" ");
sb.Append(c.ToString());
}
}
return sb.ToString();
}
}
public class CANConfig
{
public CANConfig(string name, int base_or_arb_bitrate, int base_or_arb_sjw, int data_bitrate, int data_sjw, string filetype, bool included, bool is_fd)
{
Name = name;
Base_or_arb_bitrate = base_or_arb_bitrate;
Base_or_arb_sjw = base_or_arb_sjw;
Data_bitrate = data_bitrate;
Data_sjw = data_sjw;
Filetype = filetype;
Included = included;
Is_fd = is_fd;
}
public string Name { get; }
public int Base_or_arb_bitrate { get; set; }
public int Base_or_arb_sjw { get; set; }
public int Data_bitrate { get; set; }
public int Data_sjw { get; set; }
public string Filetype { get; set; }
public bool Included { get; set; }
public bool Is_fd { get; set; }
public override string ToString()
{
return $"Name={Name}, BaseBR={Base_or_arb_bitrate}, BaseSJW={Base_or_arb_sjw}, BR={Data_bitrate}, DataSJW={Data_sjw}, FT={Filetype}, Inc={Included}, fd={Is_fd}";
}
}
}

View File

@@ -0,0 +1,141 @@
namespace CANFDApiProxy.Messages
{
internal class CANInfoInternal
{
public Can1 can1 { get; set; }
public Can2 can2 { get; set; }
public Can3 can3 { get; set; }
public Can4 can4 { get; set; }
public Pipe pipe { get; set; }
public Battery battery { get; set; }
public Pwr pwr { get; set; }
public Status status { get; set; }
public Sts sts { get; set; }
}
internal class Can1
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
internal class Can2
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
internal class Can3
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
internal class Can4
{
public string info { get; set; }
public string state { get; set; }
public float last_updated { get; set; }
public int std_data { get; set; }
public int std_remote { get; set; }
public int ext_data { get; set; }
public int ext_remote { get; set; }
public int err_frame { get; set; }
public float bus_load { get; set; }
public int overruns { get; set; }
public int base_or_arb_bitrate { get; set; }
public int base_or_arb_sjw { get; set; }
public int data_bitrate { get; set; }
public int data_sjw { get; set; }
public string filetype { get; set; }
public bool included { get; set; }
public bool is_fd { get; set; }
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
public class Pipe
{
public string path { get; set; }
}
public class Pwr
{
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
public class Status
{
public bool pin { get; set; }
}
public class Sts
{
public bool blue { get; set; }
public bool green { get; set; }
public bool red { get; set; }
}
public class Battery
{
public bool enable { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANInfoMessage
{
public List<CANInfo> CANInfoList { get; set; }
}
public class CANInfo
{
public CANInfo(string name, string info)
{
Name = name;
Info = info;
}
public string Name { get; }
public string Info { get; }
}
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANStateMessage
{
public List<CANState> CANStateList { get; set; }
}
public class CANState
{
public CANState(string name, string state, float last_updated)
{
Name = name;
State = state;
Last_updated = last_updated;
}
public string Name { get; }
public string State { get; set; }
public float Last_updated { get; set; }
}
}

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class CANStatsMessage
{
public List<CANStats> CANStatsList { get; set; }
}
public class CANStats
{
public CANStats(string name, int std_data, int std_remote, int ext_data, int ext_remote, int err_frame, float bus_load
, int overruns, float last_updated)
{
Name = name;
Last_updated = last_updated;
Std_data = std_data;
Std_remote = std_remote;
Ext_remote = ext_remote;
Err_frame = err_frame;
Bus_load = bus_load;
Ext_data = ext_data;
Overruns = overruns;
}
public string Name { get; }
public float Last_updated { get; set; }
public int Std_data { get; set; }
public int Std_remote { get; set; }
public int Ext_data { get; set; }
public int Ext_remote { get; set; }
public int Err_frame { get; set; }
public float Bus_load { get; set; }
public int Overruns { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class CalibrationMessage
{
public int Calibration_date { get; set; }
public string Calibration_date_string { get; set; }
public override string ToString()
{
return $"Calibration_date: {Calibration_date}, Calibration_date_string: {Calibration_date_string}";
}
}
}

View File

@@ -0,0 +1,10 @@
namespace CANFDApiProxy.Messages
{
public class ClocksMessage
{
public bool? Rtc_present { get; set; }
public bool? Rtc_setup { get; set; }
public string System { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace CANFDApiProxy.Messages
{
public class DeviceInfoMessage
{
public string Kernel_version { get; set; }
public string Os_release { get; set; }
public string Serial_number { get; set; }
public string Version_number { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace CANFDApiProxy.Messages
{
public class DiagnosticsMessageRequest
{
public string format { get; set; }
public override string ToString()
{
return $"format: {format}";
}
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Messages
{
public class ErrorMessage
{
public string Error { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
namespace CANFDApiProxy.Messages
{
public class EventPinMessage
{
public bool? Armed { get; set; }
public bool? Event { get; set; }
public bool? Event_pin { get; set; }
public string File_name { get; set; }
public string Ok { get; set; }
public string Reply { get; set; }
public override string ToString()
{
return $"Armed: {Armed}, Event: {Event}, Event_pin: {Event_pin}, File_name: {File_name}, Ok: {Ok}, Reply: {Reply}";
}
}
}

View File

@@ -0,0 +1,29 @@
using System.Collections.Generic;
namespace CANFDApiProxy.Messages
{
public class LEDsMessage
{
public List<LED> LEDs { get; set; }
public Battery Battery { get; set; }
public Pwr Pwr { get; set; }
public Status Status { get; set; }
public Sts Sts { get; set; }
}
public class LED
{
public LED(string name, bool blue, bool green, bool red)
{
Name = name;
Blue = blue;
Green = green;
Red = red;
}
public string Name { get; }
public bool Red { get; }
public bool Green { get; }
public bool Blue { get; }
}
}

View File

@@ -0,0 +1,8 @@
namespace CANFDApiProxy.Messages
{
public class LEDsPostMessage
{
public string status { get; set; }
public string reply { get; set; }
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class NetworkMessage
{
public string Current_address { get; set; }
public bool Dhcp { get; set; }
public string Interface { get; set; }
public string Mac_address { get; set; }
public string Set_address { get; set; }
public string Ok { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace CANFDApiProxy.Messages
{
public class NtpMessage
{
public string Ntp { get; set; }
public string Fallback { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
namespace CANFDApiProxy.Messages
{
public class PowerMessage
{
public bool Battery_enable { get; set; }
public bool Nvin_pin { get; set; }
public bool On_pin { get; set; }
public bool Power_fault { get; set; }
public string Status { get; set; }
public override string ToString()
{
return $"Battery_enable: {Battery_enable}, Nvin_pin: {Nvin_pin}, On_pin: {On_pin}, Power_fault: {Power_fault}, Status: {Status}";
}
}
}

View File

@@ -0,0 +1,15 @@
namespace CANFDApiProxy.Messages
{
public class RecordingMessage
{
public string Recording { get; set; }
public bool Autoarm { get; set; }
public string Recording_dir { get; set; }
public string Ok { get; set; }
public string Reply { get; set; }
public override string ToString()
{
return $"Recording: {Recording}, AutoArm: {Autoarm}, Recording_dir{Recording_dir}, Ok: {Ok}, Reply: {Reply}";
}
}
}

View File

@@ -0,0 +1,12 @@
namespace CANFDApiProxy.Messages
{
public class SerialMessage
{
public string Serial { get; set; }
public string Status { get; set; }
public override string ToString()
{
return $"Serial={Serial}, Status={Status}";
}
}
}

View File

@@ -0,0 +1,15 @@
namespace CANFDApiProxy.Messages
{
public class ServicesMessage
{
public Service[] services { get; set; }
}
public class Service
{
public bool Enabled { get; set; }
public string Name { get; set; }
public string Status { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace CANFDApiProxy.Messages
{
public class StatusMessage
{
public string status { get; set; }
}
}

View File

@@ -0,0 +1,117 @@
namespace CANFDApiProxy.Messages
{
public class UsbStatsMessage
{
public Filesystem Filesystem { get; set; }
public Swissbit Swissbit { get; set; }
public Traffic Traffic { get; set; }
public override string ToString()
{
return $"FS: {Filesystem}, SB: {Swissbit}, TR: {Traffic}";
}
}
public class Filesystem
{
public string avail { get; set; }
public string filesystem { get; set; }
public string mounted { get; set; }
public string size { get; set; }
public string type { get; set; }
public string use_pct { get; set; }
public string used { get; set; }
public override string ToString()
{
return $"avail: {avail}, size: {size}, use%: {use_pct}, used: {used}";
}
}
public class Swissbit
{
public Lifetime_Info lifetime_info { get; set; }
public string model { get; set; }
public string path { get; set; }
public string serial { get; set; }
public override string ToString()
{
return $"serial: {serial}, ecc: {lifetime_info.total_ecc_errors}";
}
}
public class Lifetime_Info
{
public string controller_revision { get; set; }
public int correctable_ecc_errors { get; set; }
public Erase_Info[] erase_info { get; set; }
public string firmware_revision { get; set; }
public int flash_lbas_written { get; set; }
public bool global_bad_block_management { get; set; }
public bool global_wear_leveling { get; set; }
public bool overall_health_status { get; set; }
public int power_on_counter { get; set; }
public Spare_Block_Info spare_block_info { get; set; }
public int temperature_current { get; set; }
public int temperature_max { get; set; }
public int temperature_min { get; set; }
public int total_ecc_errors { get; set; }
public int total_erase_count { get; set; }
}
public class Spare_Block_Info
{
public bool count_prefail { get; set; }
public int count_threshold { get; set; }
public bool count_valid { get; set; }
public int count_value { get; set; }
public int minimum { get; set; }
public int number_of_units { get; set; }
public int[] per_unit_current { get; set; }
public int[] per_unit_initial { get; set; }
public int total_current { get; set; }
public int total_initial { get; set; }
public int worst_current { get; set; }
public int worst_initial { get; set; }
}
public class Erase_Info
{
public Average_Erase_Count average_erase_count { get; set; }
public int erase_count { get; set; }
public string flash_cell_mode { get; set; }
public Max_Erase_Count max_erase_count { get; set; }
public bool prefail { get; set; }
public Rated_Erase_Count rated_erase_count { get; set; }
public int threshold { get; set; }
public bool valid { get; set; }
}
public class Average_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Max_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Rated_Erase_Count
{
public bool valid { get; set; }
public int value { get; set; }
}
public class Traffic
{
public float average_mbps { get; set; }
public float current_mbps { get; set; }
public float mins_remaining { get; set; }
public override string ToString()
{
return $"ave: {average_mbps}mbps, current: {current_mbps}mbps, remaining: {mins_remaining}mins";
}
}
}

Some files were not shown because too many files have changed in this diff Show More