using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Prometheus; using System.Net.Http; using System.Net.Http.Headers; using System.Text.Json; using System.Linq; namespace PrometheusExporterEdenic { public class Device { public string id { get; set; } public string name { get; set; } public string label { get; set; } // Add other properties as needed } public class ApiClient { private readonly HttpClient _client; private readonly string _authToken; private readonly string _orgid; private readonly string _apimainurl = "https://api.edenic.io/api/v1"; private string _devicename; public string DeviceName => _devicename; public string DeviceId { get; private set; } public int ph { get; private set; } public int temperature { get; private set; } public int ec { get; private set; } public async Task InitializeAsync() { DeviceId = await GetDeviceIdByName(_devicename); } public ApiClient(string authToken, string orgID, string devicename) { _client = new HttpClient(); _authToken = authToken; _orgid = orgID; _devicename = devicename; _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(_authToken); } public async Task MakeApiRequest(string path) { try { HttpResponseMessage response = await _client.GetAsync($"{_apimainurl}{path}"); Console.WriteLine($"Request send to: {_apimainurl}{path}"); if (response.IsSuccessStatusCode) { string content = await response.Content.ReadAsStringAsync(); return JsonSerializer.Deserialize(content); } else { throw new HttpRequestException($"Error: {response.StatusCode}"); } } catch (HttpRequestException e) { Console.WriteLine($"Request exception: {e.Message}"); throw; } catch (JsonException e) { Console.WriteLine($"JSON parsing exception: {e.Message}"); throw; } } public async Task GetDeviceIdByName(string name) { try { dynamic result = await MakeApiRequest($"/device/{_orgid}"); string jsonString = result.ToString(); // Convert dynamic to string Console.WriteLine($"Raw JSON: {jsonString}"); // Debug output var devices = JsonSerializer.Deserialize>(jsonString); Console.WriteLine($"Deserialized {devices.Count} devices"); // Debug output var targetDevice = devices.FirstOrDefault(d => d.label == name); if (targetDevice != null) { Console.WriteLine($"Found device: {targetDevice.label}, ID: {targetDevice.id}"); // Debug output return targetDevice.id; } else { Console.WriteLine($"No device found with label: {name}"); // Debug output return null; } } catch (Exception ex) { Console.WriteLine($"Error in GetDeviceIdByName: {ex.Message}"); // Debug output return null; } } public async Task GetTelemetry() { try { dynamic result = await MakeApiRequest($"/telemetry/{DeviceId}"); string jsonString = result.ToString(); Console.WriteLine($"Raw JSON: {jsonString}"); // Debug output using (JsonDocument doc = JsonDocument.Parse(jsonString)) { JsonElement root = doc.RootElement; ph = ExtractValue(root, "ph"); temperature = ExtractValue(root, "temperature"); ec = ExtractValue(root, "electrical_conductivity"); Console.WriteLine($"Extracted values - pH: {ph/100.0}, Temperature: {temperature/100.0}, EC: {ec/100.0}"); } } catch (Exception ex) { Console.WriteLine($"Error in GetTelemetry: {ex.Message}"); } } private int ExtractValue(JsonElement root, string key) { if (root.TryGetProperty(key, out JsonElement property) && property.GetArrayLength() > 0 && property[0].TryGetProperty("value", out JsonElement valueElement)) { string valueString = valueElement.GetString(); if (!string.IsNullOrEmpty(valueString)) { if (float.TryParse(valueString, out float floatValue)) { return (int)(floatValue * 100); // Convert to int, preserving two decimal places } else { Console.WriteLine($"Error: Unable to parse {key} value: {valueString}"); } } else { Console.WriteLine($"Error: {key} value is empty"); } } else { Console.WriteLine($"Error: {key} not found or invalid"); } return 0; // Default value } } public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMetricServer(); app.UseHttpMetrics(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", async context => { await context.Response.WriteAsync("Open /metrics"); }); }); var phGauge = Metrics.CreateGauge("edenic_ph", "Edenic ph", new GaugeConfiguration { LabelNames = new[] { "device_name" } }); var temperatureGauge = Metrics.CreateGauge("edenic_temperature", "Edenic temperature", new GaugeConfiguration { LabelNames = new[] { "device_name" } }); var ecGauge = Metrics.CreateGauge("edenic_ec", "Edenic EC", new GaugeConfiguration { LabelNames = new[] { "device_name" } }); string EDENIC_API_TOKEN = Environment.GetEnvironmentVariable("EDENIC_API_TOKEN"); string EDENIC_ORG_ID = Environment.GetEnvironmentVariable("EDENIC_ORG_ID"); string EDENIC_DEVICENAME = Environment.GetEnvironmentVariable("EDENIC_DEVICENAME"); ApiClient client = new ApiClient(EDENIC_API_TOKEN, EDENIC_ORG_ID, EDENIC_DEVICENAME); Task.Run(async () => { await client.InitializeAsync(); Console.WriteLine($"Device ID: {client.DeviceId}"); while (true) { await client.GetTelemetry(); phGauge.WithLabels(client.DeviceName).Set(client.ph / 100.0); temperatureGauge.WithLabels(client.DeviceName).Set(client.temperature / 100.0); ecGauge.WithLabels(client.DeviceName).Set(client.ec / 100.0); await Task.Delay(60000); } }); } } }