Skip to content

Commit

Permalink
Merge branch 'dev_and_test'
Browse files Browse the repository at this point in the history
  • Loading branch information
Volker Hänsel committed Oct 3, 2023
2 parents daa877a + 54b9c67 commit f288805
Show file tree
Hide file tree
Showing 25 changed files with 1,121 additions and 214 deletions.
1 change: 1 addition & 0 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ services:
dockerfile: Dockerfile
args:
GIT_COMMIT: local
DEBUGHELPER: yes
ports:
- "80"
4 changes: 4 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ services:
- 8889:80/tcp #connect to 8889 to get to the web UI
# network_mode: host
restart: on-failure
healthcheck:
test: curl --fail http://localhost:80 || exit 1
interval: 60s
retries: 5
networks:
- mqtt

Expand Down
93 changes: 77 additions & 16 deletions tuya_mqtt.net/Data/DP.cs
Original file line number Diff line number Diff line change
@@ -1,54 +1,115 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;

namespace tuya_mqtt.net.Data
{
// ReSharper disable once InconsistentNaming
public class DP
{
private readonly int _dp_no;
private readonly int _dpNo;
private readonly string _valueString;

public DP(int dpNo, string value)
{
this._dp_no = dpNo;
this._dpNo = dpNo;
this._valueString = value;
}

public static List<DP> ParseJSON(string json)
// ReSharper disable once InconsistentNaming
public static List<DP> ParseCloudJSON(string json)
{

var list = new List<DP>();
try
{
JObject bigObject = JObject.Parse(json);
var dps = bigObject["dps"];
if (dps != null)
var properties = bigObject["properties"];
if (properties != null)
{
foreach (var d in dps.Children())
foreach (var d in properties.Children())
{
var Name = ((Newtonsoft.Json.Linq.JProperty)d).Name;
var Value = d.ToObject<string>();
if (Value != null && Name != null)
var name = d["dp_id"];
var value = d["value"];

if (value != null && name != null)
{
int id;
if (int.TryParse(Name, out id))
if (int.TryParse(name.ToString(), out id))
{
list.Add(new DP(id, Value));
list.Add(new DP(id, value.ToString()));
}

}
}
}

return list;
}
catch (Exception ex)
{
throw new Exception($"error while parsing tuya device response {json}", ex);
throw new Exception($"error while parsing tuya device response '{json}'", ex);
}
}

// ReSharper disable once InconsistentNaming
public static List<DP> ParseLocalJSON(string json)
{

var list = new List<DP>();
try
{
JObject bigObject = JObject.Parse(json);
var dps = bigObject["dps"];
if (dps != null)
{
foreach (var d in dps.Children())
{
var name = ((JProperty)d).Name;
var value = d;
int id;
if (int.TryParse(name, out id))
{
list.Add(new DP(id, value.ToObject<string>()!));
}
}
}
return list;
}
catch (Exception ex)
{
throw new Exception($"error while parsing tuya device response '{json}'", ex);
}
}

// ReSharper disable once InconsistentNaming
public static string FindPropertyByDP(string json, int dpNumber)
{
try
{
JObject bigObject = JObject.Parse(json);
var properties = bigObject["properties"];
if (properties != null)
{
foreach (var d in properties.Children())
{
var name = d["dp_id"]!.ToString();
int dp;
if (int.TryParse(name, out dp))
{
if (dp == dpNumber)
return d["code"]!.ToString();
}
}
}

throw new Exception($"requested data point (DP) does not exists in '{json}'");
}
catch (Exception ex)
{
throw new Exception($"error while parsing tuya device response '{json}'", ex);
}
}

public int DPNumber { get { return _dp_no; } }
// ReSharper disable once InconsistentNaming
public int DPNumber { get { return _dpNo; } }
public string Value { get { return _valueString; } }

}
Expand Down
4 changes: 4 additions & 0 deletions tuya_mqtt.net/Data/GlobalOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
public class GlobalOptions
{
public bool MtqqReconnect { get; set; } = true;
public int ExceptionsHealthDegraded { get; set; } = 10; //>10 Exceptions per minute = degraded
public int ExceptionsUnhealthy { get; set; } = 40; //>40 Exceptions per minute = unhealthy

public TimeSpan MqttDisconnectUnhealthy { get; set; } = TimeSpan.FromMinutes(10); //10 minutes disconnect = unhealthy
}
}
32 changes: 19 additions & 13 deletions tuya_mqtt.net/Data/TimedDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,33 @@ private void CheckTimer(object? state)
finally { _rwl.ReleaseReaderLock(); }
}



private void CleanupDictionary()
{
foreach (var i in _dictionary)
try
{
if (!_cachedData.TryGetValue<byte>(i.Key, out _))

foreach (var i in _dictionary)
{
LockCookie lc = _rwl.UpgradeToWriterLock(TimeOut);
try
if (!_cachedData.TryGetValue<byte>(i.Key, out _))
{
_dictionary.Remove(i.Key);
LockCookie lc = _rwl.UpgradeToWriterLock(TimeOut);
try
{
_dictionary.Remove(i.Key);
}
finally
{
_rwl.DowngradeFromWriterLock(ref lc);
}

OnListUpdated?.Invoke(this, i.Value);
}
finally
{
_rwl.DowngradeFromWriterLock(ref lc);
}

OnListUpdated?.Invoke(this, i.Value);
}
}
catch
{
//ignore
}
}

IEnumerator IEnumerable.GetEnumerator()
Expand Down
31 changes: 30 additions & 1 deletion tuya_mqtt.net/Data/TuyaCommunicatorOptions.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,36 @@
namespace tuya_mqtt.net.Data
using com.clusterrr.TuyaNet;
using System.Reflection;

namespace tuya_mqtt.net.Data
{
public class TuyaCommunicatorOptions
{
public TuyaCommunicatorOptions() { }

public string TuyaAPIAccessID { get; set; } = String.Empty;

public string TuyaAPISecret { get; set; } = String.Empty;

public TuyaApi.Region TuyaAPIRegion { get; set; } = TuyaApi.Region.WesternEurope;

public bool Equals(TuyaCommunicatorOptions? x)
{
return x?.TuyaAPIAccessID == TuyaAPIAccessID &&
x?.TuyaAPISecret == TuyaAPISecret &&
x?.TuyaAPIRegion.GetHashCode() == TuyaAPIRegion.GetHashCode();
}

public override string ToString()
{
Type type = GetType();
var collectionString = type.Name + " (";
foreach (PropertyInfo prop in type.GetProperties())
{
collectionString += $" {prop.Name}:{prop.GetValue(this)}";
}

collectionString += " )";
return collectionString;
}
}
}
8 changes: 8 additions & 0 deletions tuya_mqtt.net/Data/TuyaDeviceInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@ namespace tuya_mqtt.net.Data
{
public class TuyaDeviceInformation
{
public enum DeviceType
{
LocalTuya = 1,
Cloud =10,

}
public TuyaDeviceInformation(TuyaDeviceInformation device)
{
this.ID = device.ID;
this.Address = device.Address;
this.Key = device.Key;
this.ProtocolVersion = device.ProtocolVersion;
this.CommunicationType = device.CommunicationType;
}

public TuyaDeviceInformation()
Expand All @@ -22,6 +29,7 @@ public TuyaDeviceInformation()
public string Key { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public TuyaProtocolVersion ProtocolVersion { get; set; } = TuyaProtocolVersion.V33;
public DeviceType CommunicationType { get; set; } = DeviceType.LocalTuya;

}

Expand Down
13 changes: 9 additions & 4 deletions tuya_mqtt.net/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
ENV DOTNET_CLI_HOME=/tmp
WORKDIR /app
EXPOSE 80

ARG DEBUGHELPER
ENV TZ=EUROPE/Berlin
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN apt-get update
RUN apt install -y tzdata
RUN apt install -y arping inetutils-ping libnet-ifconfig-wrapper-perl mc
HEALTHCHECK CMD curl --fail http://localhost:80/health || exit
RUN apt-get update && \
apt install -y curl

RUN if [ "$DEBUGHELPER" = "yes" ] ; then \
apt install -y tzdata && \
apt install -y arping inetutils-ping libnet-ifconfig-wrapper-perl mc \
; fi

FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
Expand Down Expand Up @@ -48,4 +52,5 @@ RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .

ENTRYPOINT ["dotnet", "tuya_mqtt.net.dll"]
26 changes: 26 additions & 0 deletions tuya_mqtt.net/Helper/HealthCheckResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace tuya_mqtt.net.Helper
{
public class HealthCheckResponse
{
public static Task WriteResponse(HttpContext context, HealthReport result)
{
context.Response.ContentType = "application/json";

var json = new JObject(
new JProperty("status", result.Status.ToString()),
new JProperty("results", new JObject(result.Entries.Select(pair =>
new JProperty(pair.Key, new JObject(
new JProperty("status", pair.Value.Status.ToString()),
new JProperty("description", pair.Value.Description),
new JProperty("data", new JObject(pair.Value.Data.Select(
p => new JProperty(p.Key, p.Value))))))))));

return context.Response.WriteAsync(
json.ToString(Formatting.Indented));
}
}
}
43 changes: 43 additions & 0 deletions tuya_mqtt.net/Helper/RateCounter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Collections.Generic;

namespace tuya_mqtt.net.Helper
{
public class RateCounter
{
private readonly List<DateTime> _counter = new List <DateTime>();
private readonly TimeSpan _duration;
public RateCounter(TimeSpan duration)
{
_duration = duration;

}
public void Clear()
{
_counter.Clear();
}
public void Count()
{
_counter.Add(DateTime.UtcNow);
Cleanup();
}

private void Cleanup()
{
IEnumerable<DateTime> enumerableThing = _counter;
foreach (var x in enumerableThing.Reverse())
{
if ((x + _duration) < DateTime.UtcNow )
_counter.Remove(x);
}
}

public int Rate
{
get
{
Cleanup();
return _counter.Count;
}
}
}
}

0 comments on commit f288805

Please sign in to comment.