Compare commits
20 Commits
efe6863b14
...
dev
Author | SHA1 | Date | |
---|---|---|---|
3c19797f72 | |||
fdf74f5f52 | |||
20a9b726a4 | |||
da62e176cd | |||
368de74820 | |||
8cb2a51cd3 | |||
d2cd0f0fe0 | |||
1a69dad891 | |||
488211e307 | |||
d24b3592ac | |||
1b099f2a5e | |||
b8c838caa3 | |||
ecfcd26b47 | |||
4b537633f6 | |||
15a7332931 | |||
be6b9cc537 | |||
2b0aefba60 | |||
10983bea7f | |||
e60298b8a3 | |||
2161900a09 |
106
.github/workflows/nuget.yml
vendored
Normal file
106
.github/workflows/nuget.yml
vendored
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
||||||
|
|
||||||
|
name: publish
|
||||||
|
on:
|
||||||
|
workflow_dispatch: # Allow running the workflow manually from the GitHub UI
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main' # Run the workflow when pushing to the main branch
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- '*' # Run the workflow for all pull requests
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- published # Run the workflow when a new GitHub release is published
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
|
||||||
|
DOTNET_NOLOGO: true
|
||||||
|
NuGetDirectory: ${{ github.workspace}}/nuget
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: pwsh
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
create_nuget:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # Get all history to allow automatic versioning using MinVer
|
||||||
|
|
||||||
|
# Install the .NET SDK indicated in the global.json file
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
|
||||||
|
# Create the NuGet package in the folder from the environment variable NuGetDirectory
|
||||||
|
- run: dotnet pack --configuration Release --output ${{ env.NuGetDirectory }}
|
||||||
|
|
||||||
|
# Publish the NuGet package as an artifact, so they can be used in the following jobs
|
||||||
|
- uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: nuget
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 7
|
||||||
|
path: ${{ env.NuGetDirectory }}/*.nupkg
|
||||||
|
|
||||||
|
validate_nuget:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ create_nuget ]
|
||||||
|
steps:
|
||||||
|
# Install the .NET SDK indicated in the global.json file
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
|
||||||
|
# Download the NuGet package created in the previous job
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: nuget
|
||||||
|
path: ${{ env.NuGetDirectory }}
|
||||||
|
|
||||||
|
- name: Install nuget validator
|
||||||
|
run: dotnet tool update Meziantou.Framework.NuGetPackageValidation.Tool --global
|
||||||
|
|
||||||
|
# Validate metadata and content of the NuGet package
|
||||||
|
# https://www.nuget.org/packages/Meziantou.Framework.NuGetPackageValidation.Tool#readme-body-tab
|
||||||
|
# If some rules are not applicable, you can disable them
|
||||||
|
# using the --excluded-rules or --excluded-rule-ids option
|
||||||
|
- name: Validate package
|
||||||
|
run: meziantou.validate-nuget-package (Get-ChildItem "${{ env.NuGetDirectory }}/*.nupkg")
|
||||||
|
|
||||||
|
run_test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
- name: Run tests
|
||||||
|
run: dotnet test --configuration Release
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
# Publish only when creating a GitHub Release
|
||||||
|
# https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
|
||||||
|
# You can update this logic if you want to manage releases differently
|
||||||
|
if: github.event_name == 'release'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ validate_nuget, run_test ]
|
||||||
|
steps:
|
||||||
|
# Download the NuGet package created in the previous job
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: nuget
|
||||||
|
path: ${{ env.NuGetDirectory }}
|
||||||
|
|
||||||
|
# Install the .NET SDK indicated in the global.json file
|
||||||
|
- name: Setup .NET Core
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
|
||||||
|
# Publish all NuGet packages to NuGet.org
|
||||||
|
# Use --skip-duplicate to prevent errors if a package with the same version already exists.
|
||||||
|
# If you retry a failed workflow, already published packages will be skipped without error.
|
||||||
|
- name: Publish NuGet package
|
||||||
|
run: |
|
||||||
|
foreach($file in (Get-ChildItem "${{ env.NuGetDirectory }}" -Recurse -Include *.nupkg)) {
|
||||||
|
dotnet nuget push $file --api-key "${{ secrets.NUGET_KEY }}" --source https://api.nuget.org/v3/index.json --skip-duplicate
|
||||||
|
}
|
32
.gitignore
vendored
32
.gitignore
vendored
@ -1,5 +1,33 @@
|
|||||||
bin/
|
# Common IntelliJ Platform excludes
|
||||||
obj/
|
|
||||||
|
# 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/
|
/packages/
|
||||||
riderModule.iml
|
riderModule.iml
|
||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
@ -2,8 +2,6 @@
|
|||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoveeCSharpConnector", "GoveeCSharpConnector\GoveeCSharpConnector.csproj", "{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoveeCSharpConnector", "GoveeCSharpConnector\GoveeCSharpConnector.csproj", "{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoveeCsharpConnector.Example", "GoveeCsharpConnector.Example\GoveeCsharpConnector.Example.csproj", "{E487B84B-F619-430A-A0D3-80D44FE9EE3F}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -14,9 +12,5 @@ Global
|
|||||||
{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}.Release|Any CPU.Build.0 = Release|Any CPU
|
{EDF67B3A-9EBF-4C76-92E2-0AACD6B8081B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{E487B84B-F619-430A-A0D3-80D44FE9EE3F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{E487B84B-F619-430A-A0D3-80D44FE9EE3F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{E487B84B-F619-430A-A0D3-80D44FE9EE3F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{E487B84B-F619-430A-A0D3-80D44FE9EE3F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Govee/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Govee/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=reauired/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -5,16 +5,22 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>disable</Nullable>
|
<Nullable>disable</Nullable>
|
||||||
<LangVersion>latest</LangVersion>
|
<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>
|
||||||
|
<PackageReadmeFile>../README.md</PackageReadmeFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
<PackageReference Include="System.Net.Http.Json" Version="8.0.0" />
|
||||||
<PackageReference Include="System.Reactive" Version="6.0.0" />
|
<PackageReference Include="System.Reactive" Version="6.0.0" />
|
||||||
<PackageReference Include="System.Text.Json" Version="8.0.1" />
|
<PackageReference Include="System.Text.Json" Version="8.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Properties\" />
|
<Folder Include="Properties\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -1,8 +1,9 @@
|
|||||||
using GoveeCSharpConnector.Objects;
|
using GoveeCSharpConnector.Objects;
|
||||||
|
using GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
namespace GoveeCSharpConnector.Interfaces;
|
namespace GoveeCSharpConnector.Interfaces;
|
||||||
|
|
||||||
public interface IGoveeApiService
|
public interface IGoveeHttpService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the required Api Key for the Govee Api.
|
/// Sets the required Api Key for the Govee Api.
|
||||||
@ -22,15 +23,15 @@ public interface IGoveeApiService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Requests all Devices registered to Api Key Govee Account
|
/// Requests all Devices registered to Api Key Govee Account
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>List of GoveeApiDevices</returns>
|
/// <returns>List of GoveeHttpDevices</returns>
|
||||||
Task<List<GoveeApiDevice>> GetDevices();
|
Task<ServiceResponse<List<GoveeHttpDevice>>> GetDevices();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Requests the State of a single Govee Device
|
/// Requests the State of a single Govee Device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="deviceId">Device Id Guid as string</param>
|
/// <param name="deviceId">Device Id Guid as string</param>
|
||||||
/// <param name="deviceModel">Device Model Number as string</param>
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
/// <returns>GoveeApiStat Object</returns>
|
/// <returns>GoveeHttpState Object</returns>
|
||||||
public Task<GoveeApiState> GetDeviceState(string deviceId, string deviceModel);
|
Task<ServiceResponse<GoveeHttpState>> GetDeviceState(string deviceId, string deviceModel);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the On/Off state of a single Govee Device
|
/// Sets the On/Off state of a single Govee Device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -38,15 +39,7 @@ public interface IGoveeApiService
|
|||||||
/// <param name="deviceModel">Device Model Number as string</param>
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
/// <param name="on"></param>
|
/// <param name="on"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task ToggleState(string deviceId, string deviceModel, bool on);
|
Task<ServiceResponse<bool>> SetOnOff(string deviceId, string deviceModel, bool on);
|
||||||
/// <summary>
|
|
||||||
/// Sets the Brightness in Percent of a single Govee Device
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="deviceId">Device Id Guid as string</param>
|
|
||||||
/// <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);
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets a Rgb Color of a single Govee Device
|
/// Sets a Rgb Color of a single Govee Device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -54,7 +47,7 @@ public interface IGoveeApiService
|
|||||||
/// <param name="deviceModel">Device Model Number as string</param>
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
/// <param name="color">Rgb Color</param>
|
/// <param name="color">Rgb Color</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task SetColor(string deviceId, string deviceModel, RgbColor color);
|
Task<ServiceResponse<bool>> SetColor(string deviceId, string deviceModel, RgbColor color);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the Color Temperature of a single Govee Device
|
/// Sets the Color Temperature of a single Govee Device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -62,6 +55,37 @@ public interface IGoveeApiService
|
|||||||
/// <param name="deviceModel">Device Model Number as string</param>
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
/// <param name="value">Color Temp in Kelvin as Int</param>
|
/// <param name="value">Color Temp in Kelvin as Int</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task SetColorTemp(string deviceId, string deviceModel, int value);
|
Task<ServiceResponse<bool>> SetColorTemp(string deviceId, string deviceModel, int value);
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the Brightness of a single Govee Device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">Device Id Guid as string</param>
|
||||||
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
|
/// <param name="value">Value 1-100</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<ServiceResponse<bool>> SetBrightness(string deviceId, string deviceModel, int value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a List of all available Govee Scenes for the Device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">Device Id Guid as string</param>
|
||||||
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<ServiceResponse<List<GoveeScene>>> GetScenes(string deviceId, string deviceModel);
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the LightScene of a single Govee Device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">Device Id Guid as string</param>
|
||||||
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
|
/// <param name="sceneValue">Number of the Scene</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<ServiceResponse<bool>> SetLightScene(string deviceId, string deviceModel, int sceneValue);
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the DiyScene of a single Govee Device
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="deviceId">Device Id Guid as string</param>
|
||||||
|
/// <param name="deviceModel">Device Model Number as string</param>
|
||||||
|
/// <param name="sceneValue">Number of the Scene</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<ServiceResponse<bool>> SetDiyScene(string deviceId, string deviceModel, int sceneValue);
|
||||||
}
|
}
|
62
GoveeCSharpConnector/Interfaces/IGoveeService.cs
Normal file
62
GoveeCSharpConnector/Interfaces/IGoveeService.cs
Normal 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);
|
||||||
|
}
|
@ -1,4 +1,8 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
using GoveeCSharpConnector.Objects;
|
using GoveeCSharpConnector.Objects;
|
||||||
|
|
||||||
namespace GoveeCSharpConnector.Interfaces;
|
namespace GoveeCSharpConnector.Interfaces;
|
||||||
@ -36,7 +40,7 @@ public interface IGoveeUdpService
|
|||||||
/// <param name="brightness">In Percent 1-100</param>
|
/// <param name="brightness">In Percent 1-100</param>
|
||||||
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
|
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task SetBrightness(string deviceAddress, short brightness, int uniCastPort = 4003);
|
Task SetBrightness(string deviceAddress, int brightness, int uniCastPort = 4003);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the Color of the Device
|
/// Sets the Color of the Device
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -45,6 +49,15 @@ public interface IGoveeUdpService
|
|||||||
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
|
/// <param name="uniCastPort">Port of the Device. Standard 4003</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task SetColor(string deviceAddress, RgbColor color, int uniCastPort = 4003);
|
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>
|
/// <summary>
|
||||||
/// Starts the Udp Listener
|
/// Starts the Udp Listener
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -60,4 +73,4 @@ public interface IGoveeUdpService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
void StopUdpListener();
|
void StopUdpListener();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
namespace GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
public class ApiResponse
|
|
||||||
{
|
|
||||||
public string? Message { get; set; }
|
|
||||||
public int Code { get; set; }
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
public class Data
|
|
||||||
{
|
|
||||||
public List<GoveeApiDevice> Devices { get; set; }
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
namespace GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
public class GoveeApiCommand
|
|
||||||
{
|
|
||||||
public string Device { get; set; }
|
|
||||||
public string Model { get; set; }
|
|
||||||
public Command Cmd { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Command
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public object Value { get; set; }
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
public class GoveeApiDevice
|
|
||||||
{
|
|
||||||
[JsonPropertyName("device")]
|
|
||||||
public string DeviceId { get; set; }
|
|
||||||
public string Model { get; set; }
|
|
||||||
public string DeviceName { get; set; }
|
|
||||||
public bool Controllable { get; set; }
|
|
||||||
public bool Retrievable { get; set; }
|
|
||||||
[JsonPropertyName("supportCmds")]
|
|
||||||
public List<string> SupportedCommands { get; set; }
|
|
||||||
public Properties Properties { get; set; }
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
public class GoveeApiState
|
|
||||||
{
|
|
||||||
[JsonPropertyName("device")]
|
|
||||||
public string DeviceId { get; set; }
|
|
||||||
|
|
||||||
public string Model { get; set; }
|
|
||||||
|
|
||||||
public string Name { get; set; }
|
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public Properties Properties { get; set; }
|
|
||||||
}
|
|
9
GoveeCSharpConnector/Objects/GoveeDevice.cs
Normal file
9
GoveeCSharpConnector/Objects/GoveeDevice.cs
Normal 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; }
|
||||||
|
}
|
14
GoveeCSharpConnector/Objects/GoveeHttpDevice.cs
Normal file
14
GoveeCSharpConnector/Objects/GoveeHttpDevice.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects;
|
||||||
|
|
||||||
|
public class GoveeHttpDevice
|
||||||
|
{
|
||||||
|
[JsonPropertyName("sku")]
|
||||||
|
public string Model { get; set; }
|
||||||
|
[JsonPropertyName("device")]
|
||||||
|
public string Device { get; set; }
|
||||||
|
[JsonPropertyName("capabilities")]
|
||||||
|
public List<Capability> Capabilities { get; set; }
|
||||||
|
}
|
16
GoveeCSharpConnector/Objects/GoveeHttpState.cs
Normal file
16
GoveeCSharpConnector/Objects/GoveeHttpState.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects;
|
||||||
|
|
||||||
|
public class GoveeHttpState
|
||||||
|
{
|
||||||
|
[JsonPropertyName("requestId")]
|
||||||
|
public string RequestId { get; set; }
|
||||||
|
[JsonPropertyName("msg")]
|
||||||
|
public string Msg { get; set; }
|
||||||
|
[JsonPropertyName("code")]
|
||||||
|
public long Code { get; set; }
|
||||||
|
[JsonPropertyName("payload")]
|
||||||
|
public Payload Payload { get; set; }
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
namespace GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
public class GoveeResponse : ApiResponse
|
|
||||||
{
|
|
||||||
public Data Data { get; set; }
|
|
||||||
}
|
|
13
GoveeCSharpConnector/Objects/GoveeScene.cs
Normal file
13
GoveeCSharpConnector/Objects/GoveeScene.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects;
|
||||||
|
|
||||||
|
public class GoveeScene
|
||||||
|
{
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("value")]
|
||||||
|
public SceneValue SceneValue { get; set; }
|
||||||
|
}
|
@ -2,11 +2,10 @@ using GoveeCSharpConnector.Enums;
|
|||||||
|
|
||||||
namespace GoveeCSharpConnector.Objects;
|
namespace GoveeCSharpConnector.Objects;
|
||||||
|
|
||||||
public class Properties
|
public class GoveeState
|
||||||
{
|
{
|
||||||
public bool Online { get; set; }
|
public PowerState State { get; set; }
|
||||||
public PowerState PowerState { get; set; }
|
|
||||||
public int Brightness { get; set; }
|
public int Brightness { get; set; }
|
||||||
public int? ColorTemp { get; set; }
|
|
||||||
public RgbColor Color { get; set; }
|
public RgbColor Color { get; set; }
|
||||||
|
public int ColorTempInKelvin { get; set; }
|
||||||
}
|
}
|
13
GoveeCSharpConnector/Objects/Misc/ApiResponse.cs
Normal file
13
GoveeCSharpConnector/Objects/Misc/ApiResponse.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class ApiResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("code")]
|
||||||
|
public int Code { get; set; }
|
||||||
|
[JsonPropertyName("message")]
|
||||||
|
public string Message { get; set; }
|
||||||
|
[JsonPropertyName("data")]
|
||||||
|
public List<object> Data { get; set; }
|
||||||
|
}
|
13
GoveeCSharpConnector/Objects/Misc/Capability.cs
Normal file
13
GoveeCSharpConnector/Objects/Misc/Capability.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Capability
|
||||||
|
{
|
||||||
|
[JsonPropertyName("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
[JsonPropertyName("instance")]
|
||||||
|
public string Instance { get; set; }
|
||||||
|
[JsonPropertyName("state")]
|
||||||
|
public State State { get; set; }
|
||||||
|
}
|
21
GoveeCSharpConnector/Objects/Misc/Field.cs
Normal file
21
GoveeCSharpConnector/Objects/Misc/Field.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Field
|
||||||
|
{
|
||||||
|
[JsonPropertyName("fieldName")]
|
||||||
|
public string FieldName { get; set; }
|
||||||
|
[JsonPropertyName("dataType")]
|
||||||
|
public string DataType { get; set; }
|
||||||
|
[JsonPropertyName("options")]
|
||||||
|
public List<Option> Options { get; set; }
|
||||||
|
[JsonPropertyName("required")]
|
||||||
|
public bool Required { get; set; }
|
||||||
|
[JsonPropertyName("range")]
|
||||||
|
public Range Range { get; set; }
|
||||||
|
[JsonPropertyName("unit")]
|
||||||
|
public string Unit { get; set; }
|
||||||
|
[JsonPropertyName("reauired")]
|
||||||
|
public bool? Reauired { get; set; }
|
||||||
|
}
|
11
GoveeCSharpConnector/Objects/Misc/Option.cs
Normal file
11
GoveeCSharpConnector/Objects/Misc/Option.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Option
|
||||||
|
{
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonPropertyName("value")]
|
||||||
|
public int Value { get; set; }
|
||||||
|
}
|
17
GoveeCSharpConnector/Objects/Misc/Parameters.cs
Normal file
17
GoveeCSharpConnector/Objects/Misc/Parameters.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Parameters
|
||||||
|
{
|
||||||
|
[JsonPropertyName("dataType")]
|
||||||
|
public string DataType { get; set; }
|
||||||
|
[JsonPropertyName("options")]
|
||||||
|
public List<Option> Options { get; set; }
|
||||||
|
[JsonPropertyName("unit")]
|
||||||
|
public string Unit { get; set; }
|
||||||
|
[JsonPropertyName("range")]
|
||||||
|
public Range Range { get; set; }
|
||||||
|
[JsonPropertyName("fields")]
|
||||||
|
public List<Field> Fields { get; set; }
|
||||||
|
}
|
13
GoveeCSharpConnector/Objects/Misc/Payload.cs
Normal file
13
GoveeCSharpConnector/Objects/Misc/Payload.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Payload
|
||||||
|
{
|
||||||
|
[JsonPropertyName("sku")]
|
||||||
|
public string Model { get; set; }
|
||||||
|
[JsonPropertyName("device")]
|
||||||
|
public string Device { get; set; }
|
||||||
|
[JsonPropertyName("capabilities")]
|
||||||
|
public List<Capability> Capabilities { get; set; }
|
||||||
|
}
|
18
GoveeCSharpConnector/Objects/Misc/Properties.cs
Normal file
18
GoveeCSharpConnector/Objects/Misc/Properties.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using GoveeCSharpConnector.Enums;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Properties
|
||||||
|
{
|
||||||
|
[JsonPropertyName("online")]
|
||||||
|
public bool Online { get; set; }
|
||||||
|
[JsonPropertyName("powerState")]
|
||||||
|
public PowerState PowerState { get; set; }
|
||||||
|
[JsonPropertyName("brightness")]
|
||||||
|
public int Brightness { get; set; }
|
||||||
|
[JsonPropertyName("colorTemp")]
|
||||||
|
public int ColorTemp { get; set; }
|
||||||
|
[JsonPropertyName("color")]
|
||||||
|
public RgbColor Color { get; set; }
|
||||||
|
}
|
13
GoveeCSharpConnector/Objects/Misc/Range.cs
Normal file
13
GoveeCSharpConnector/Objects/Misc/Range.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class Range
|
||||||
|
{
|
||||||
|
[JsonPropertyName("min")]
|
||||||
|
public int Min { get; set; }
|
||||||
|
[JsonPropertyName("max")]
|
||||||
|
public int Max { get; set; }
|
||||||
|
[JsonPropertyName("precision")]
|
||||||
|
public int Precision { get; set; }
|
||||||
|
}
|
12
GoveeCSharpConnector/Objects/Misc/SceneValue.cs
Normal file
12
GoveeCSharpConnector/Objects/Misc/SceneValue.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class SceneValue
|
||||||
|
{
|
||||||
|
[JsonPropertyName("paramId")]
|
||||||
|
public long ParamId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
}
|
8
GoveeCSharpConnector/Objects/Misc/ServiceResponse.cs
Normal file
8
GoveeCSharpConnector/Objects/Misc/ServiceResponse.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class ServiceResponse<T>
|
||||||
|
{
|
||||||
|
public T? Data { get; set; }
|
||||||
|
public bool Success { get; set; } = true;
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
}
|
9
GoveeCSharpConnector/Objects/Misc/State.cs
Normal file
9
GoveeCSharpConnector/Objects/Misc/State.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
public class State
|
||||||
|
{
|
||||||
|
[JsonPropertyName("value")]
|
||||||
|
public object Value { get; set; }
|
||||||
|
}
|
@ -1,82 +0,0 @@
|
|||||||
using System.Net.Http.Json;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using GoveeCSharpConnector.Interfaces;
|
|
||||||
using GoveeCSharpConnector.Objects;
|
|
||||||
|
|
||||||
namespace GoveeCSharpConnector.Services;
|
|
||||||
|
|
||||||
public class GoveeApiService : IGoveeApiService
|
|
||||||
{
|
|
||||||
private string _apiKey = string.Empty;
|
|
||||||
private const string GoveeApiAddress = "https://developer-api.govee.com/v1";
|
|
||||||
private readonly HttpClient _httpClient = new();
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void SetApiKey(string apiKey)
|
|
||||||
{
|
|
||||||
_apiKey = apiKey;
|
|
||||||
_httpClient.DefaultRequestHeaders.Add("Govee-API-Key", _apiKey);
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public string GetApiKey()
|
|
||||||
{
|
|
||||||
return _apiKey;
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public void RemoveApiKey()
|
|
||||||
{
|
|
||||||
_apiKey = string.Empty;
|
|
||||||
_httpClient.DefaultRequestHeaders.Remove("Govee-Api-Key");
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<List<GoveeApiDevice>> GetDevices()
|
|
||||||
{
|
|
||||||
var response = await _httpClient.GetFromJsonAsync<GoveeResponse>($"{GoveeApiAddress}/devices");
|
|
||||||
|
|
||||||
return response.Data.Devices;
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task<GoveeApiState> GetDeviceState(string deviceId, string deviceModel)
|
|
||||||
{
|
|
||||||
return await _httpClient.GetFromJsonAsync<GoveeApiState>($"{GoveeApiAddress}/devices/state?device={deviceId}&model={deviceModel}");
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task ToggleState(string deviceId, string deviceModel, bool on)
|
|
||||||
{
|
|
||||||
await SendCommand(deviceId, deviceModel, "turn", on ? "on" : "off");
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task SetBrightness(string deviceId, string deviceModel, int value)
|
|
||||||
{
|
|
||||||
await SendCommand(deviceId, deviceModel, "brightness", value);
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task SetColor(string deviceId, string deviceModel, RgbColor color)
|
|
||||||
{
|
|
||||||
await SendCommand(deviceId, deviceModel, "color", color);
|
|
||||||
}
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public async Task SetColorTemp(string deviceId, string deviceModel, int value)
|
|
||||||
{
|
|
||||||
await SendCommand(deviceId, deviceModel, "colorTem", value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SendCommand(string deviceId, string deviceModel, string command, object commandObject)
|
|
||||||
{
|
|
||||||
var commandRequest = new GoveeApiCommand()
|
|
||||||
{
|
|
||||||
Device = deviceId,
|
|
||||||
Model = deviceModel,
|
|
||||||
Cmd = new Command()
|
|
||||||
{
|
|
||||||
Name = command,
|
|
||||||
Value = commandObject
|
|
||||||
}
|
|
||||||
};
|
|
||||||
var httpContent = new StringContent(JsonSerializer.Serialize(commandRequest), 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}");
|
|
||||||
}
|
|
||||||
}
|
|
306
GoveeCSharpConnector/Services/GoveeHttpService.cs
Normal file
306
GoveeCSharpConnector/Services/GoveeHttpService.cs
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using GoveeCSharpConnector.Interfaces;
|
||||||
|
using GoveeCSharpConnector.Objects;
|
||||||
|
using GoveeCSharpConnector.Objects.Misc;
|
||||||
|
|
||||||
|
namespace GoveeCSharpConnector.Services;
|
||||||
|
|
||||||
|
public class GoveeHttpService : IGoveeHttpService
|
||||||
|
{
|
||||||
|
private string _apiKey = string.Empty;
|
||||||
|
private const string GoveeApiAddress = "https://openapi.api.govee.com";
|
||||||
|
private const string GoveeDevicesEndpoint = "/router/api/v1/user/devices";
|
||||||
|
private const string GoveeControlEndpoint = "/router/api/v1/device/control";
|
||||||
|
private const string GoveeStateEndpoint = "/router/api/v1/device/state";
|
||||||
|
private const string GoveeScenesEndpoint = "/router/api/v1/device/scenes";
|
||||||
|
private readonly HttpClient _httpClient = new();
|
||||||
|
private readonly JsonSerializerOptions? _jsonOptions = new()
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
};
|
||||||
|
|
||||||
|
public GoveeHttpService()
|
||||||
|
{
|
||||||
|
_httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void SetApiKey(string apiKey)
|
||||||
|
{
|
||||||
|
_apiKey = apiKey;
|
||||||
|
_httpClient.DefaultRequestHeaders.Add("Govee-API-Key", _apiKey);
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string GetApiKey()
|
||||||
|
{
|
||||||
|
return _apiKey;
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public void RemoveApiKey()
|
||||||
|
{
|
||||||
|
_apiKey = string.Empty;
|
||||||
|
_httpClient.DefaultRequestHeaders.Remove("Govee-API-Key");
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<List<GoveeHttpDevice>>> GetDevices()
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<List<GoveeHttpDevice>>();
|
||||||
|
var response = await _httpClient.GetFromJsonAsync<ApiResponse>($"{GoveeApiAddress}{GoveeDevicesEndpoint}");
|
||||||
|
if (response.Code != 200)
|
||||||
|
{
|
||||||
|
if (response.Code == 429)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = "Api Limit reached! 10000/Account/Day";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.Message;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
var allDevices = response.Data.OfType<GoveeHttpDevice>().ToList();
|
||||||
|
|
||||||
|
var devices = (from device in allDevices where device.Capabilities.Exists(x => x.Type == "devices.capabilities.on_off")
|
||||||
|
where device.Capabilities.Exists(x => x.Type == "devices.capabilities.color_setting")
|
||||||
|
where device.Capabilities.Exists(x => x.Type == "devices.capabilities.range")
|
||||||
|
where device.Capabilities.Exists(x => x.Type == "devices.capabilities.dynamic_scene")
|
||||||
|
select device).ToList();
|
||||||
|
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Data = devices;
|
||||||
|
serviceResponse.Message = "Request Successful";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<GoveeHttpState>> GetDeviceState(string deviceId, string deviceModel)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<GoveeHttpState>();
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}""
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeStateEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = await response.Content.ReadFromJsonAsync<GoveeHttpState>();
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
serviceResponse.Data = state;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<bool>> SetOnOff(string deviceId, string deviceModel, bool on)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<bool>();
|
||||||
|
|
||||||
|
var value = "0";
|
||||||
|
if (on)
|
||||||
|
{
|
||||||
|
value = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}"",
|
||||||
|
""capability"": {{
|
||||||
|
""type"": ""devices.capabilities.on_off"",
|
||||||
|
""instance"": ""powerSwitch"",
|
||||||
|
""value"": {value}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeControlEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<bool>> SetColor(string deviceId, string deviceModel, RgbColor color)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<bool>();
|
||||||
|
|
||||||
|
var value = ((color.R & 0xFF) << 16) | ((color.G & 0xFF) << 8) | (color.B & 0xFF);
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}"",
|
||||||
|
""capability"": {{
|
||||||
|
""type"": ""devices.capabilities.color_setting"",
|
||||||
|
""instance"": ""colorRgb"",
|
||||||
|
""value"": {value}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeControlEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ServiceResponse<bool>> SetColorTemp(string deviceId, string deviceModel, int value)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<bool>> SetBrightness(string deviceId, string deviceModel, int value)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<bool>();
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}"",
|
||||||
|
""capability"": {{
|
||||||
|
""type"": ""devices.capabilities.range"",
|
||||||
|
""instance"": ""brightness"",
|
||||||
|
""value"": {value}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeControlEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<List<GoveeScene>>> GetScenes(string deviceId, string deviceModel)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<List<GoveeScene>>();
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}""
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeControlEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
// TODO Test response Content
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<bool>> SetLightScene(string deviceId, string deviceModel, int sceneValue)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<bool>();
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}"",
|
||||||
|
""capability"": {{
|
||||||
|
""type"": ""devices.capabilities.dynamic_scene"",
|
||||||
|
""instance"": ""lightScene"",
|
||||||
|
""value"": {sceneValue}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeControlEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public async Task<ServiceResponse<bool>> SetDiyScene(string deviceId, string deviceModel, int sceneValue)
|
||||||
|
{
|
||||||
|
var serviceResponse = new ServiceResponse<bool>();
|
||||||
|
|
||||||
|
var jsonPayload = $@"
|
||||||
|
{{
|
||||||
|
""requestId"": ""{Guid.NewGuid()}"",
|
||||||
|
""payload"": {{
|
||||||
|
""sku"": ""{deviceModel}"",
|
||||||
|
""device"": ""{deviceId}"",
|
||||||
|
""capability"": {{
|
||||||
|
""type"": ""devices.capabilities.dynamic_scene"",
|
||||||
|
""instance"": ""diyScene"",
|
||||||
|
""value"": {sceneValue}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}";
|
||||||
|
|
||||||
|
var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync($"{GoveeApiAddress}{GoveeControlEndpoint}", content);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
serviceResponse.Success = false;
|
||||||
|
serviceResponse.Message = response.ReasonPhrase;
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceResponse.Success = true;
|
||||||
|
serviceResponse.Message = "";
|
||||||
|
return serviceResponse;
|
||||||
|
}
|
||||||
|
}
|
106
GoveeCSharpConnector/Services/GoveeService.cs
Normal file
106
GoveeCSharpConnector/Services/GoveeService.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -38,9 +38,9 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Build Message
|
// Build Message
|
||||||
var message = new GoveeUdpMessage()
|
var message = new GoveeUdpMessage
|
||||||
{
|
{
|
||||||
msg = new msg()
|
msg = new msg
|
||||||
{
|
{
|
||||||
cmd = "scan",
|
cmd = "scan",
|
||||||
data = new { account_topic = "reserve" }
|
data = new { account_topic = "reserve" }
|
||||||
@ -48,7 +48,7 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
};
|
};
|
||||||
// Subscribe to ScanResultSubject
|
// Subscribe to ScanResultSubject
|
||||||
var devicesTask = _scanResultSubject
|
var devicesTask = _scanResultSubject
|
||||||
.TakeUntil(Observable.Timer(timeout ?? TimeSpan.FromMilliseconds(200)))
|
.TakeUntil(Observable.Timer(timeout ?? TimeSpan.FromMilliseconds(300)))
|
||||||
.ToList()
|
.ToList()
|
||||||
.ToTask();
|
.ToTask();
|
||||||
|
|
||||||
@ -76,9 +76,9 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Build Message
|
// Build Message
|
||||||
var message = new GoveeUdpMessage()
|
var message = new GoveeUdpMessage
|
||||||
{
|
{
|
||||||
msg = new msg()
|
msg = new msg
|
||||||
{
|
{
|
||||||
cmd = "devStatus",
|
cmd = "devStatus",
|
||||||
data = new { }
|
data = new { }
|
||||||
@ -107,9 +107,9 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Build Message
|
// Build Message
|
||||||
var message = new GoveeUdpMessage()
|
var message = new GoveeUdpMessage
|
||||||
{
|
{
|
||||||
msg = new msg()
|
msg = new msg
|
||||||
{
|
{
|
||||||
cmd = "turn",
|
cmd = "turn",
|
||||||
data = new { value = on ? 1 : 0 }
|
data = new { value = on ? 1 : 0 }
|
||||||
@ -126,14 +126,14 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task SetBrightness(string deviceAddress, short brightness, int uniCastPort = 4003)
|
public async Task SetBrightness(string deviceAddress, int brightness, int uniCastPort = 4003)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Build Message
|
// Build Message
|
||||||
var message = new GoveeUdpMessage()
|
var message = new GoveeUdpMessage
|
||||||
{
|
{
|
||||||
msg = new msg()
|
msg = new msg
|
||||||
{
|
{
|
||||||
cmd = "brightness",
|
cmd = "brightness",
|
||||||
data = new { value = brightness }
|
data = new { value = brightness }
|
||||||
@ -155,9 +155,9 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Build Message
|
// Build Message
|
||||||
var message = new GoveeUdpMessage()
|
var message = new GoveeUdpMessage
|
||||||
{
|
{
|
||||||
msg = new msg()
|
msg = new msg
|
||||||
{
|
{
|
||||||
cmd = "colorwc",
|
cmd = "colorwc",
|
||||||
data = new
|
data = new
|
||||||
@ -173,7 +173,6 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
};
|
};
|
||||||
// Send Message
|
// Send Message
|
||||||
SendUdpMessage(JsonSerializer.Serialize(message), deviceAddress, uniCastPort);
|
SendUdpMessage(JsonSerializer.Serialize(message), deviceAddress, uniCastPort);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@ -181,6 +180,39 @@ public class GoveeUdpService : IGoveeUdpService
|
|||||||
throw;
|
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/>
|
/// <inheritdoc/>
|
||||||
public async void StartUdpListener()
|
public async void StartUdpListener()
|
||||||
{
|
{
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\GoveeCSharpConnector\GoveeCSharpConnector.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
@ -1,202 +0,0 @@
|
|||||||
using System.Net.Mime;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using GoveeCSharpConnector.Objects;
|
|
||||||
using GoveeCSharpConnector.Services;
|
|
||||||
|
|
||||||
namespace GoveeCsharpConnector.Example;
|
|
||||||
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
private static GoveeApiService _goveeApiService = new GoveeApiService();
|
|
||||||
public static List<GoveeApiDevice> _apiDevices = new List<GoveeApiDevice>();
|
|
||||||
|
|
||||||
public static async Task Main(string[] args)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
PrintWelcomeMessage();
|
|
||||||
var input = Console.ReadLine();
|
|
||||||
HandleKeyInput(input);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async void HandleKeyInput(string input)
|
|
||||||
{
|
|
||||||
switch (input)
|
|
||||||
{
|
|
||||||
case "1":
|
|
||||||
HandleApiInput();
|
|
||||||
EndSegment();
|
|
||||||
break;
|
|
||||||
case "2":
|
|
||||||
Console.WriteLine("Requesting Devices ...");
|
|
||||||
_apiDevices = await _goveeApiService.GetDevices();
|
|
||||||
Console.WriteLine("Devices:");
|
|
||||||
foreach (var device in _apiDevices)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Name: {device.DeviceName}, Device Id: {device.DeviceId}, Model: {device.Model}, Controllable {device.Controllable}");
|
|
||||||
}
|
|
||||||
Console.WriteLine($"Total: {_apiDevices.Count} Devices.");
|
|
||||||
EndSegment();
|
|
||||||
|
|
||||||
break;
|
|
||||||
case "3":
|
|
||||||
if (_apiDevices.Count == 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("No Devices discovered! Please use Option 2 first!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Console.WriteLine("Please enter the Name of the Device:");
|
|
||||||
var nameInput = Console.ReadLine()?.ToLower();
|
|
||||||
if (string.IsNullOrWhiteSpace(nameInput) || _apiDevices.FirstOrDefault(x => x.DeviceName.ToLower() == nameInput) is null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Device Name Invalid!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"Do you want to turn the Device {nameInput} on or off?");
|
|
||||||
var onOffInput = Console.ReadLine()?.ToLower();
|
|
||||||
if (string.IsNullOrWhiteSpace(onOffInput) || (onOffInput != "on" && onOffInput != "off"))
|
|
||||||
{
|
|
||||||
Console.WriteLine("Invalid Input!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input == "on")
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
EndSegment();
|
|
||||||
break;
|
|
||||||
case "4":
|
|
||||||
if (_apiDevices.Count == 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("No Devices discovered! Please use Option 2 first!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Console.WriteLine("Please enter the Name of the Device:");
|
|
||||||
var nameInput2 = Console.ReadLine()?.ToLower();
|
|
||||||
if (string.IsNullOrWhiteSpace(nameInput2) || _apiDevices.FirstOrDefault(x => x.DeviceName.ToLower() == nameInput2) is null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Device Name Invalid!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"Please enter a Brightness Value for Device {nameInput2}. 0-100");
|
|
||||||
var brightnessInput = Console.ReadLine();
|
|
||||||
int value = Convert.ToInt16(brightnessInput);
|
|
||||||
if (string.IsNullOrWhiteSpace(brightnessInput) || value < 0 || value > 100)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Invalid Input!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
case "5":
|
|
||||||
if (_apiDevices.Count == 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("No Devices discovered! Please use Option 2 first!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Console.WriteLine("Please enter the Name of the Device:");
|
|
||||||
var nameInput3 = Console.ReadLine()?.ToLower();
|
|
||||||
if (string.IsNullOrWhiteSpace(nameInput3) || _apiDevices.FirstOrDefault(x => x.DeviceName.ToLower() == nameInput3) is null)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Device Name Invalid!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
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")
|
|
||||||
{
|
|
||||||
Console.WriteLine("Invalid Input!");
|
|
||||||
EndSegment();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var model = _apiDevices.FirstOrDefault(x => x.DeviceName.ToLower()== nameInput3)?.Model;
|
|
||||||
switch (colorInput)
|
|
||||||
{
|
|
||||||
case "blue":
|
|
||||||
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));
|
|
||||||
break;
|
|
||||||
case "red":
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void HandleApiInput()
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Please enter/paste your Govee Api Key ...");
|
|
||||||
Console.WriteLine("Your Api Key should look something like this: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
|
|
||||||
var input = Console.ReadLine();
|
|
||||||
if (input is null || input.Length != 36)
|
|
||||||
{
|
|
||||||
Console.WriteLine("Wrong Api Key Format!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_goveeApiService.SetApiKey(input);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Console.WriteLine("Api Key saved!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EndSegment()
|
|
||||||
{
|
|
||||||
Console.WriteLine("---------------------------Press any Key to continue---------------------------");
|
|
||||||
Console.ReadLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void PrintWelcomeMessage()
|
|
||||||
{
|
|
||||||
Console.WriteLine();
|
|
||||||
Console.WriteLine("Welcome to the GoveeCSharpConnector Example!");
|
|
||||||
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()))
|
|
||||||
{
|
|
||||||
Console.WriteLine("1 - Enter GoveeApi Key - START HERE (Required for Api Service Options!)");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine("1 - Enter GoveeApi Key - Already Set!");
|
|
||||||
Console.WriteLine("Api Service:");
|
|
||||||
Console.WriteLine("2 - Get a List of all Devices connected to the Api Key Account");
|
|
||||||
Console.WriteLine("3 - Turn Device On or Off");
|
|
||||||
Console.WriteLine("4 - Set Brightness for Device");
|
|
||||||
Console.WriteLine("5 - Set Color of Device");
|
|
||||||
}
|
|
||||||
Console.WriteLine("Udp Service - No Api Key needed!");
|
|
||||||
Console.WriteLine("6 - Get a List of all Devices available in the Network");
|
|
||||||
Console.WriteLine("7 - Turn Device On or Off");
|
|
||||||
Console.WriteLine("8 - Set Brightness for Device");
|
|
||||||
Console.WriteLine("9 - Set Color of Device");
|
|
||||||
}
|
|
||||||
}
|
|
21
LICENSE
Normal file
21
LICENSE
Normal 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.
|
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# GoveeCSharpConnector
|
||||||
|
|
||||||
|

|
||||||
|
[](https://www.nuget.org/packages/GoveeCSharpConnector/)
|
||||||
|
# About
|
||||||
|
|
||||||
|
Simple .net Library to interface with Govee Smart Lights via their Web Api or Lan Udp connection.
|
Reference in New Issue
Block a user