Compare commits

...

10 Commits

Author SHA1 Message Date
76ccf20c30 Fixed UdpDeviceList Pick
Fixed UdpListener Start
2024-02-03 12:23:34 +01:00
a069133a68 Set Api Key (#4)
* Delete .gitignore

* Added Readme, Added Nuget Infos in Project

* Added GoveeService that unites Api and Udp Service

Added ColorTemp Method to Udp Service

* Added UdpListener check

* Added ApiKey check

* Moved Class and changed Namespace

* Update GoveeCSharpConnector.csproj

* Set Api Key on Request
2024-02-03 01:25:44 +01:00
bb01b3342d Version 1.1.0 (#3)
* Delete .gitignore

* Added Readme, Added Nuget Infos in Project

* Added GoveeService that unites Api and Udp Service

Added ColorTemp Method to Udp Service

* Added UdpListener check

* Added ApiKey check

* Moved Class and changed Namespace

* Update GoveeCSharpConnector.csproj
2024-02-03 00:57:33 +01:00
602926c43e Create nuget.yml
Add Nuget Action
2024-02-02 19:21:45 +01:00
2eef997c6e Update README.md (#2) 2024-02-02 19:06:51 +01:00
bb9364c491 Dev (#1)
* Delete .gitignore

* Added Readme, Added Nuget Infos in Project
2024-02-02 19:05:57 +01:00
be6b9cc537 Create LICENSE 2024-02-02 18:50:52 +01:00
10983bea7f Finished Udp Example Options 2024-02-02 18:11:08 +01:00
e60298b8a3 Fixed color check
Added Json Options for Api Request
2024-02-02 16:47:50 +01:00
2161900a09 Modify Gitignore 2024-02-02 16:39:07 +01:00
15 changed files with 486 additions and 49 deletions

27
.github/workflows/nuget.yml vendored Normal file
View File

@ -0,0 +1,27 @@
name: Release to NuGet
on:
push:
branches:
- master # Default release branch
pull_request:
branches:
- master # Run the workflow for all pull requests on Branch Master
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- name: Setup .NET SDK
uses: actions/setup-dotnet@v1.5
- name: Build
run: dotnet build -c Release
- name: Test
run: dotnet test -c Release --no-build
- name: Pack nugets
run: dotnet pack -c Release --no-build --output .
- name: Push to NuGet
run: dotnet nuget push "*.nupkg" --api-key ${{secrets.NUGET_KEY}} --source https://api.nuget.org/v3/index.json

32
.gitignore vendored
View File

@ -1,5 +1,33 @@
bin/
obj/
# Common IntelliJ Platform excludes
# User specific
**/.idea/**/workspace.xml
**/.idea/**/tasks.xml
**/.idea/shelf/*
**/.idea/dictionaries
**/.idea/httpRequests/
# Sensitive or high-churn files
**/.idea/**/dataSources/
**/.idea/**/dataSources.ids
**/.idea/**/dataSources.xml
**/.idea/**/dataSources.local.xml
**/.idea/**/sqlDataSources.xml
**/.idea/**/dynamic.xml
# Rider
# Rider auto-generates .iml files, and contentModel.xml
**/.idea/**/*.iml
**/.idea/**/contentModel.xml
**/.idea/**/modules.xml
*.suo
*.user
.vs/
[Bb]in/
[Oo]bj/
_UpgradeReport_Files/
[Pp]ackages/
/packages/
riderModule.iml
/_ReSharper.Caches/

View File

@ -5,16 +5,21 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Title>CSharp Library to control Govee Lights via Govee Web Api and Lan Udp!</Title>
<Authors>Locxion</Authors>
<Description>CSharp Library to control Govee Lights via Govee Web Api and Lan Udp!</Description>
<PackageProjectUrl>https://github.com/Locxion/GoveeCSharpConnector</PackageProjectUrl>
<RepositoryUrl>https://github.com/Locxion/GoveeCSharpConnector</RepositoryUrl>
<PackageLicenseUrl>https://github.com/Locxion/GoveeCSharpConnector/blob/main/LICENSE</PackageLicenseUrl>
<Version>1.1.2</Version>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
<PackageReference Include="System.Reactive" Version="6.0.0" />
<PackageReference Include="System.Text.Json" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
</Project>

View File

@ -10,27 +10,32 @@ public interface IGoveeApiService
/// </summary>
/// <param name="apiKey">Api Key as String</param>
void SetApiKey(string apiKey);
/// <summary>
/// Returns current set Govee Api Key
/// </summary>
/// <returns>Govee Api Key as String</returns>
string GetApiKey();
/// <summary>
/// Removes the Set Api Key and resets the HTTP Header
/// </summary>
void RemoveApiKey();
/// <summary>
/// Requests all Devices registered to Api Key Govee Account
/// </summary>
/// <returns>List of GoveeApiDevices</returns>
Task<List<GoveeApiDevice>> GetDevices();
/// <summary>
/// Requests the State of a single Govee Device
/// </summary>
/// <param name="deviceId">Device Id Guid as string</param>
/// <param name="deviceModel">Device Model Number as string</param>
/// <returns>GoveeApiStat Object</returns>
public Task<GoveeApiState> GetDeviceState(string deviceId, string deviceModel);
Task<GoveeApiState> GetDeviceState(string deviceId, string deviceModel);
/// <summary>
/// Sets the On/Off state of a single Govee Device
/// </summary>
@ -38,7 +43,8 @@ public interface IGoveeApiService
/// <param name="deviceModel">Device Model Number as string</param>
/// <param name="on"></param>
/// <returns></returns>
public Task ToggleState(string deviceId, string deviceModel, bool on);
Task ToggleState(string deviceId, string deviceModel, bool on);
/// <summary>
/// Sets the Brightness in Percent of a single Govee Device
/// </summary>
@ -46,7 +52,8 @@ public interface IGoveeApiService
/// <param name="deviceModel">Device Model Number as string</param>
/// <param name="value">Brightness in Percent as Int</param>
/// <returns></returns>
public Task SetBrightness(string deviceId, string deviceModel, int value);
Task SetBrightness(string deviceId, string deviceModel, int value);
/// <summary>
/// Sets a Rgb Color of a single Govee Device
/// </summary>
@ -54,7 +61,8 @@ public interface IGoveeApiService
/// <param name="deviceModel">Device Model Number as string</param>
/// <param name="color">Rgb Color</param>
/// <returns></returns>
public Task SetColor(string deviceId, string deviceModel, RgbColor color);
Task SetColor(string deviceId, string deviceModel, RgbColor color);
/// <summary>
/// Sets the Color Temperature of a single Govee Device
/// </summary>
@ -62,6 +70,5 @@ public interface IGoveeApiService
/// <param name="deviceModel">Device Model Number as string</param>
/// <param name="value">Color Temp in Kelvin as Int</param>
/// <returns></returns>
public Task SetColorTemp(string deviceId, string deviceModel, int value);
Task SetColorTemp(string deviceId, string deviceModel, int value);
}

View File

@ -0,0 +1,62 @@
using GoveeCSharpConnector.Objects;
namespace GoveeCSharpConnector.Interfaces;
public interface IGoveeService
{
/// <summary>
/// Govee Api Key
/// </summary>
string GoveeApiKey { get; set; }
/// <summary>
/// Gets a List of Govee Devices
/// </summary>
/// <param name="onlyLan">If true returns that are available on Api and Lan</param>
/// <returns>List of Govee Devices</returns>
Task<List<GoveeDevice>> GetDevices(bool onlyLan = true);
/// <summary>
/// Gets the State of a GoveeDevice
/// </summary>
/// <param name="goveeDevice">GoveeDevice</param>
/// <param name="useUdp">Use Udp Connection instead of the Api</param>
/// <returns></returns>
Task<GoveeState> GetDeviceState(GoveeDevice goveeDevice, bool useUdp = true);
/// <summary>
/// Sets the On/Off State of the GoveeDevice
/// </summary>
/// <param name="goveeDevice">GoveeDevice</param>
/// <param name="on"></param>
/// <param name="useUdp">Use Udp Connection instead of the Api</param>
/// <returns></returns>
Task ToggleState(GoveeDevice goveeDevice, bool on, bool useUdp = true);
/// <summary>
/// Sets the Brightness of the GoveeDevice
/// </summary>
/// <param name="goveeDevice">GoveeDevice</param>
/// <param name="value">Brightness in Percent</param>
/// <param name="useUdp">Use Udp Connection instead of the Api</param>
/// <returns></returns>
Task SetBrightness(GoveeDevice goveeDevice, int value, bool useUdp = true);
/// <summary>
/// Sets the Color of the GoveeDevice
/// </summary>
/// <param name="goveeDevice">GoveeDevice</param>
/// <param name="color">RgBColor</param>
/// <param name="useUdp">Use Udp Connection instead of the Api</param>
/// <returns></returns>
Task SetColor(GoveeDevice goveeDevice, RgbColor color, bool useUdp = true);
/// <summary>
/// Sets the Color Temperature in Kelvin for the GoveeDevice
/// </summary>
/// <param name="goveeDevice">GoveeDevice</param>
/// <param name="value">Color Temp in Kelvin</param>
/// <param name="useUdp">Use Udp Connection instead of the Api</param>
/// <returns></returns>
Task SetColorTemp(GoveeDevice goveeDevice, int value, bool useUdp = true);
}

View File

@ -1,4 +1,8 @@
using System.Data;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using GoveeCSharpConnector.Objects;
namespace GoveeCSharpConnector.Interfaces;
@ -8,7 +12,7 @@ public interface IGoveeUdpService
/// <summary>
/// Sends a Scan Command via Udp Multicast.
/// </summary>
/// <param name="timeout">Standard 200ms</param>
/// <param name="timeout">Standard 250ms</param>
/// <returns>List of GoveeUdpDevices</returns>
Task<List<GoveeUdpDevice>> GetDevices(TimeSpan? timeout = null);
@ -17,7 +21,7 @@ public interface IGoveeUdpService
/// </summary>
/// <param name="deviceAddress">Ip Address of the Device</param>
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
/// <param name="timeout">Standard 200ms</param>
/// <param name="timeout">Standard 250ms</param>
/// <returns></returns>
Task<GoveeUdpState> GetState(string deviceAddress, int uniCastPort = 4003, TimeSpan? timeout = null);
@ -36,7 +40,7 @@ public interface IGoveeUdpService
/// <param name="brightness">In Percent 1-100</param>
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
/// <returns></returns>
Task SetBrightness(string deviceAddress, short brightness, int uniCastPort = 4003);
Task SetBrightness(string deviceAddress, int brightness, int uniCastPort = 4003);
/// <summary>
/// Sets the Color of the Device
/// </summary>
@ -45,6 +49,15 @@ public interface IGoveeUdpService
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
/// <returns></returns>
Task SetColor(string deviceAddress, RgbColor color, int uniCastPort = 4003);
/// <summary>
/// Sets the ColorTemp of the Device
/// </summary>
/// <param name="deviceAddress">Ip Address of the Device</param>
/// <param name="colorTempInKelvin"></param>
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
/// <returns></returns>
Task SetColorTemp(string deviceAddress, int colorTempInKelvin, int uniCastPort = 4003);
/// <summary>
/// Starts the Udp Listener
/// </summary>

View File

@ -0,0 +1,9 @@
namespace GoveeCSharpConnector.Objects;
public class GoveeDevice
{
public string DeviceId { get; set; }
public string Model { get; set; }
public string DeviceName { get; set; }
public string Address { get; set; }
}

View File

@ -0,0 +1,11 @@
using GoveeCSharpConnector.Enums;
namespace GoveeCSharpConnector.Objects;
public class GoveeState
{
public PowerState State { get; set; }
public int Brightness { get; set; }
public RgbColor Color { get; set; }
public int ColorTempInKelvin { get; set; }
}

View File

@ -7,6 +7,6 @@ public class Properties
public bool Online { get; set; }
public PowerState PowerState { get; set; }
public int Brightness { get; set; }
public int? ColorTemp { get; set; }
public int ColorTemp { get; set; }
public RgbColor Color { get; set; }
}

View File

@ -11,7 +11,10 @@ public class GoveeApiService : IGoveeApiService
private string _apiKey = string.Empty;
private const string GoveeApiAddress = "https://developer-api.govee.com/v1";
private readonly HttpClient _httpClient = new();
private readonly JsonSerializerOptions? _jsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};
/// <inheritdoc/>
public void SetApiKey(string apiKey)
{
@ -74,7 +77,7 @@ public class GoveeApiService : IGoveeApiService
Value = commandObject
}
};
var httpContent = new StringContent(JsonSerializer.Serialize(commandRequest), Encoding.UTF8, "application/json");
var httpContent = new StringContent(JsonSerializer.Serialize(commandRequest, _jsonOptions), Encoding.UTF8, "application/json");
var response = await _httpClient.PutAsync($"{GoveeApiAddress}/devices/control", httpContent);
if (!response.IsSuccessStatusCode)
throw new Exception($"Govee Api Request failed. Status code: {response.StatusCode}, Message: {response.Content}");

View File

@ -0,0 +1,108 @@
using GoveeCSharpConnector.Interfaces;
using GoveeCSharpConnector.Objects;
namespace GoveeCSharpConnector.Services;
public class GoveeService : IGoveeService
{
public string GoveeApiKey { get; set; }
private readonly IGoveeApiService _apiService;
private readonly IGoveeUdpService _udpService;
public GoveeService(IGoveeApiService apiService,IGoveeUdpService udpService)
{
_apiService = apiService ?? throw new ArgumentNullException(nameof(apiService));
_udpService = udpService ?? throw new ArgumentNullException(nameof(udpService));
}
public async Task<List<GoveeDevice>> GetDevices(bool onlyLan = true)
{
if (string.IsNullOrWhiteSpace(GoveeApiKey)) throw new Exception("No Govee Api Key Set!");
_apiService.SetApiKey(GoveeApiKey);
var apiDevices = await _apiService.GetDevices();
var devices = apiDevices.Select(apiDevice => new GoveeDevice() { DeviceId = apiDevice.DeviceId, DeviceName = apiDevice.DeviceName, Model = apiDevice.Model, Address = "onlyAvailableOnUdpRequest" }).ToList();
if (!onlyLan)
return devices;
if (!_udpService.IsListening())
_udpService.StartUdpListener();
var udpDevices = await _udpService.GetDevices();
var combinedDevices = (from goveeDevice in devices let matchingDevice = udpDevices.FirstOrDefault(x => x.device == goveeDevice.DeviceId)
where matchingDevice is not null select
new GoveeDevice { DeviceId = goveeDevice.DeviceId, DeviceName = goveeDevice.DeviceName, Model = goveeDevice.Model, Address = matchingDevice.ip }).ToList();
return combinedDevices;
}
public async Task<GoveeState> GetDeviceState(GoveeDevice goveeDevice, bool useUdp = true)
{
if (useUdp)
{
if (!_udpService.IsListening())
_udpService.StartUdpListener();
if (string.IsNullOrWhiteSpace(goveeDevice.Address)) throw new Exception("Device not available via Udp/Lan");
var udpState = await _udpService.GetState(goveeDevice.Address);
return new GoveeState() { State = udpState.onOff, Brightness = udpState.brightness, Color = udpState.color, ColorTempInKelvin = udpState.colorTempInKelvin };
}
if (string.IsNullOrWhiteSpace(GoveeApiKey)) throw new Exception("No Govee Api Key Set!");
_apiService.SetApiKey(GoveeApiKey);
var apiState = await _apiService.GetDeviceState(goveeDevice.DeviceId, goveeDevice.Model);
return new GoveeState{State = apiState.Properties.PowerState, Brightness = apiState.Properties.Brightness, Color = apiState.Properties.Color, ColorTempInKelvin = apiState.Properties.ColorTemp};
}
public async Task ToggleState(GoveeDevice goveeDevice, bool on, bool useUdp = true)
{
if (useUdp)
{
if (string.IsNullOrWhiteSpace(goveeDevice.Address)) throw new Exception("Device not available via Udp/Lan");
await _udpService.ToggleDevice(goveeDevice.Address, on);
return;
}
if (string.IsNullOrWhiteSpace(GoveeApiKey)) throw new Exception("No Govee Api Key Set!");
_apiService.SetApiKey(GoveeApiKey);
await _apiService.ToggleState(goveeDevice.DeviceId, goveeDevice.Model, on);
}
public async Task SetBrightness(GoveeDevice goveeDevice, int value, bool useUdp = true)
{
if (useUdp)
{
if (string.IsNullOrWhiteSpace(goveeDevice.Address)) throw new Exception("Device not available via Udp/Lan");
await _udpService.SetBrightness(goveeDevice.Address, value);
return;
}
if (string.IsNullOrWhiteSpace(GoveeApiKey)) throw new Exception("No Govee Api Key Set!");
_apiService.SetApiKey(GoveeApiKey);
await _apiService.SetBrightness(goveeDevice.DeviceId, goveeDevice.Model, value);
}
public async Task SetColor(GoveeDevice goveeDevice, RgbColor color, bool useUdp = true)
{
if (useUdp)
{
if (string.IsNullOrWhiteSpace(goveeDevice.Address)) throw new Exception("Device not available via Udp/Lan");
await _udpService.SetColor(goveeDevice.Address, color);
return;
}
if (string.IsNullOrWhiteSpace(GoveeApiKey)) throw new Exception("No Govee Api Key Set!");
_apiService.SetApiKey(GoveeApiKey);
await _apiService.SetColor(goveeDevice.DeviceId, goveeDevice.Model, color);
}
public async Task SetColorTemp(GoveeDevice goveeDevice, int value, bool useUdp = true)
{
if (useUdp)
{
if (string.IsNullOrWhiteSpace(goveeDevice.Address)) throw new Exception("Device not available via Udp/Lan");
await _udpService.SetColorTemp(goveeDevice.Address, value);
return;
}
if (string.IsNullOrWhiteSpace(GoveeApiKey)) throw new Exception("No Govee Api Key Set!");
_apiService.SetApiKey(GoveeApiKey);
await _apiService.SetColorTemp(goveeDevice.DeviceId, goveeDevice.Model, value);
}
}

View File

@ -32,15 +32,17 @@ public class GoveeUdpService : IGoveeUdpService
/// <inheritdoc/>
public async Task<List<GoveeUdpDevice>> GetDevices(TimeSpan? timeout = null)
{
if (!_udpListenerActive)
throw new Exception("Udp Listener not started!");
// Block this Method until current call reaches end of Method
await _semaphore.WaitAsync();
try
{
// Build Message
var message = new GoveeUdpMessage()
var message = new GoveeUdpMessage
{
msg = new msg()
msg = new msg
{
cmd = "scan",
data = new { account_topic = "reserve" }
@ -48,7 +50,7 @@ public class GoveeUdpService : IGoveeUdpService
};
// Subscribe to ScanResultSubject
var devicesTask = _scanResultSubject
.TakeUntil(Observable.Timer(timeout ?? TimeSpan.FromMilliseconds(200)))
.TakeUntil(Observable.Timer(timeout ?? TimeSpan.FromMilliseconds(250)))
.ToList()
.ToTask();
@ -73,12 +75,14 @@ public class GoveeUdpService : IGoveeUdpService
/// <inheritdoc/>
public async Task<GoveeUdpState> GetState(string deviceAddress, int uniCastPort = 4003, TimeSpan? timeout = null)
{
if (!_udpListenerActive)
throw new Exception("Udp Listener not started!");
try
{
// Build Message
var message = new GoveeUdpMessage()
var message = new GoveeUdpMessage
{
msg = new msg()
msg = new msg
{
cmd = "devStatus",
data = new { }
@ -86,7 +90,7 @@ public class GoveeUdpService : IGoveeUdpService
};
// Subscribe to ScanResultSubject
var devicesTask = _stateResultSubject
.TakeUntil(Observable.Timer(timeout ?? TimeSpan.FromMilliseconds(200)))
.TakeUntil(Observable.Timer(timeout ?? TimeSpan.FromMilliseconds(250)))
.ToTask();
// Send Message
@ -107,9 +111,9 @@ public class GoveeUdpService : IGoveeUdpService
try
{
// Build Message
var message = new GoveeUdpMessage()
var message = new GoveeUdpMessage
{
msg = new msg()
msg = new msg
{
cmd = "turn",
data = new { value = on ? 1 : 0 }
@ -126,14 +130,14 @@ public class GoveeUdpService : IGoveeUdpService
}
}
/// <inheritdoc/>
public async Task SetBrightness(string deviceAddress, short brightness, int uniCastPort = 4003)
public async Task SetBrightness(string deviceAddress, int brightness, int uniCastPort = 4003)
{
try
{
// Build Message
var message = new GoveeUdpMessage()
var message = new GoveeUdpMessage
{
msg = new msg()
msg = new msg
{
cmd = "brightness",
data = new { value = brightness }
@ -155,9 +159,9 @@ public class GoveeUdpService : IGoveeUdpService
try
{
// Build Message
var message = new GoveeUdpMessage()
var message = new GoveeUdpMessage
{
msg = new msg()
msg = new msg
{
cmd = "colorwc",
data = new
@ -173,7 +177,6 @@ public class GoveeUdpService : IGoveeUdpService
};
// Send Message
SendUdpMessage(JsonSerializer.Serialize(message), deviceAddress, uniCastPort);
}
catch (Exception e)
{
@ -181,6 +184,39 @@ public class GoveeUdpService : IGoveeUdpService
throw;
}
}
public async Task SetColorTemp(string deviceAddress, int colorTempInKelvin, int uniCastPort = 4003)
{
try
{
// Build Message
var message = new GoveeUdpMessage
{
msg = new msg
{
cmd = "colorwc",
data = new
{
color = new
{
r = 0,
g = 0,
b = 0
},
colorTempInKelvin = colorTempInKelvin
}
}
};
// Send Message
SendUdpMessage(JsonSerializer.Serialize(message), deviceAddress, uniCastPort);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
/// <inheritdoc/>
public async void StartUdpListener()
{
@ -196,6 +232,8 @@ public class GoveeUdpService : IGoveeUdpService
public void StopUdpListener()
{
_udpListenerActive = false;
_udpClient.DropMulticastGroup(IPAddress.Parse(GoveeMulticastAddress));
_udpClient.Close();
}
private static void SendUdpMessage(string message, string receiverAddress, int receiverPort)
@ -217,12 +255,13 @@ public class GoveeUdpService : IGoveeUdpService
}
}
private void SetupUdpClientListener()
private async void SetupUdpClientListener()
{
_udpClient.ExclusiveAddressUse = false;
var localEndPoint = new IPEndPoint(IPAddress.Any, GoveeMulticastPortListen);
_udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_udpClient.Client.Bind(localEndPoint);
await StartListener();
}
private async Task StartListener()
@ -245,10 +284,9 @@ public class GoveeUdpService : IGoveeUdpService
}
});
}
finally
catch(Exception ex)
{
_udpClient.DropMulticastGroup(IPAddress.Parse(GoveeMulticastAddress));
_udpClient.Close();
throw ex;
}
}

View File

@ -8,8 +8,10 @@ namespace GoveeCsharpConnector.Example;
public class Program
{
private static GoveeApiService _goveeApiService = new GoveeApiService();
public static List<GoveeApiDevice> _apiDevices = new List<GoveeApiDevice>();
private static readonly GoveeApiService GoveeApiService = new ();
private static readonly GoveeUdpService GoveeUdpService = new ();
private static List<GoveeApiDevice> _apiDevices = new ();
private static List<GoveeUdpDevice> _udpDevices = new();
public static async Task Main(string[] args)
{
@ -31,7 +33,7 @@ public class Program
break;
case "2":
Console.WriteLine("Requesting Devices ...");
_apiDevices = await _goveeApiService.GetDevices();
_apiDevices = await GoveeApiService.GetDevices();
Console.WriteLine("Devices:");
foreach (var device in _apiDevices)
{
@ -39,7 +41,6 @@ public class Program
}
Console.WriteLine($"Total: {_apiDevices.Count} Devices.");
EndSegment();
break;
case "3":
if (_apiDevices.Count == 0)
@ -68,11 +69,11 @@ public class Program
if (input == "on")
{
await _goveeApiService.ToggleState(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput).DeviceId, _apiDevices.First(x => x.DeviceName.ToLower() == nameInput).Model, true);
await GoveeApiService.ToggleState(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput).DeviceId, _apiDevices.First(x => x.DeviceName.ToLower() == nameInput).Model, true);
}
else
{
await _goveeApiService.ToggleState(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput).DeviceId, _apiDevices.First(x => x.DeviceName.ToLower() == nameInput).Model, false);
await GoveeApiService.ToggleState(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput).DeviceId, _apiDevices.First(x => x.DeviceName.ToLower() == nameInput).Model, false);
}
EndSegment();
break;
@ -102,7 +103,7 @@ public class Program
return;
}
await _goveeApiService.SetBrightness(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput2).DeviceId, _apiDevices.First(x => x.DeviceName.ToLower() == nameInput2).Model, value);
await GoveeApiService.SetBrightness(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput2).DeviceId, _apiDevices.First(x => x.DeviceName.ToLower() == nameInput2).Model, value);
Console.WriteLine($"Set Brightness of Device {nameInput2} to {value}%!");
EndSegment();
break;
@ -123,7 +124,7 @@ public class Program
}
Console.WriteLine($"Please choose a Color to set {nameInput3} to ... (blue, red, green)");
var colorInput = Console.ReadLine()?.ToLower();
if (string.IsNullOrWhiteSpace(colorInput) || colorInput != "blue" || colorInput != "green" || colorInput != "red")
if (string.IsNullOrWhiteSpace(colorInput) || (colorInput != "blue" && colorInput != "green" && colorInput != "red"))
{
Console.WriteLine("Invalid Input!");
EndSegment();
@ -134,19 +135,115 @@ public class Program
switch (colorInput)
{
case "blue":
await _goveeApiService.SetColor(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput3).DeviceId, model, new RgbColor(0, 0 ,254));
await GoveeApiService.SetColor(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput3).DeviceId, model, new RgbColor(0, 0 ,254));
break;
case "green":
await _goveeApiService.SetColor(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput3).DeviceId, model, new RgbColor(0, 254 ,0));
await GoveeApiService.SetColor(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput3).DeviceId, model, new RgbColor(0, 254 ,0));
break;
case "red":
await _goveeApiService.SetColor(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput3).DeviceId, model, new RgbColor(254, 0 ,0));
await GoveeApiService.SetColor(_apiDevices.First(x => x.DeviceName.ToLower() == nameInput3).DeviceId, model, new RgbColor(254, 0 ,0));
break;
}
Console.WriteLine($"Set Color of Device {nameInput3} to {colorInput}!");
EndSegment();
break;
case "6":
Console.WriteLine("Requesting Devices ...");
_udpDevices = await GoveeUdpService.GetDevices();
Console.WriteLine("Devices:");
foreach (var device in _udpDevices)
{
Console.WriteLine($"IpAddress: {device.ip}, Device Id: {device.device}, Model: {device.sku}");
}
Console.WriteLine($"Total: {_udpDevices.Count} Devices.");
EndSegment();
break;
case "7":
var selectedDevice = GetUdpDeviceSelection();
Console.WriteLine($"Do you want to turn the Device {selectedDevice.ip} on or off?");
var onOffInput2 = Console.ReadLine()?.ToLower();
if (string.IsNullOrWhiteSpace(onOffInput2) || (onOffInput2 != "on" && onOffInput2 != "off"))
{
Console.WriteLine("Invalid Input!");
EndSegment();
return;
}
if (input == "on")
{
await GoveeUdpService.ToggleDevice(selectedDevice.ip, true);
}
else
{
await GoveeUdpService.ToggleDevice(selectedDevice.ip, false);
}
EndSegment();
break;
case "8":
var selectedDevice2 = GetUdpDeviceSelection();
Console.WriteLine($"Please enter a Brightness Value for Device {selectedDevice2.ip}. 0-100");
var brightnessInput2 = Console.ReadLine();
int value2 = Convert.ToInt16(brightnessInput2);
if (string.IsNullOrWhiteSpace(brightnessInput2) || value2 < 0 || value2 > 100)
{
Console.WriteLine("Invalid Input!");
EndSegment();
return;
}
await GoveeUdpService.SetBrightness(selectedDevice2.ip, value2);
Console.WriteLine($"Set Brightness of Device {selectedDevice2.ip} to {value2}%!");
EndSegment();
break;
case "9":
var selectedDevice3 = GetUdpDeviceSelection();
Console.WriteLine($"Please choose a Color to set {selectedDevice3.ip} to ... (blue, red, green)");
var colorInput2 = Console.ReadLine()?.ToLower();
if (string.IsNullOrWhiteSpace(colorInput2) || (colorInput2 != "blue" && colorInput2 != "green" && colorInput2 != "red"))
{
Console.WriteLine("Invalid Input!");
EndSegment();
return;
}
switch (colorInput2)
{
case "blue":
GoveeUdpService.SetColor(selectedDevice3.ip, new RgbColor(0, 0, 254));
break;
case "green":
GoveeUdpService.SetColor(selectedDevice3.ip, new RgbColor(0, 254, 0));
break;
case "red":
GoveeUdpService.SetColor(selectedDevice3.ip, new RgbColor(254, 0, 0));
break;
}
Console.WriteLine($"Set Color of Device {selectedDevice3.ip} to {colorInput2}!");
EndSegment();
break;
}
}
private static GoveeUdpDevice GetUdpDeviceSelection()
{
var count = 1;
Console.WriteLine("Please Choose a Device from the List:");
foreach (var device in _udpDevices)
{
Console.WriteLine($"{count} - IpAdress: {device.ip}, Device Id {device.device}, Model {device.sku}");
count++;
}
var input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input) || Int16.TryParse(input, out var result) is false)
{
Console.WriteLine("Invalid Input!");
return GetUdpDeviceSelection();
}
return _udpDevices[result-1];
}
private static void HandleApiInput()
@ -161,7 +258,7 @@ public class Program
Console.WriteLine("Wrong Api Key Format!");
continue;
}
_goveeApiService.SetApiKey(input);
GoveeApiService.SetApiKey(input);
break;
}
Console.WriteLine("Api Key saved!");
@ -180,7 +277,7 @@ public class Program
Console.WriteLine($"Version: {Assembly.GetEntryAssembly()?.GetName().Version}");
Console.WriteLine($"To test/explore the GoveeCSharpConnector Version: {Assembly.Load("GoveeCSharpConnector").GetName().Version}");
Console.WriteLine("----------------------------------------------------------");
if (string.IsNullOrEmpty(_goveeApiService.GetApiKey()))
if (string.IsNullOrEmpty(GoveeApiService.GetApiKey()))
{
Console.WriteLine("1 - Enter GoveeApi Key - START HERE (Required for Api Service Options!)");
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Locxion
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

8
README.md Normal file
View File

@ -0,0 +1,8 @@
# GoveeCSharpConnector
![netStandard2.0](https://img.shields.io/badge/.NET%20Standard-2.0-blueviolet)
[![Nuget](https://img.shields.io/nuget/v/GoveeCSharpConnector?cacheSeconds=50)](https://www.nuget.org/packages/GoveeCSharpConnector/)
# About
Simple .net Library to interface with Govee Smart Lights via their Web Api or Lan Udp connection.