feat: минорые изменения после тестирования

This commit is contained in:
2025-11-28 14:20:24 +03:00
parent 5ff0384def
commit d50557a581
12 changed files with 80 additions and 28 deletions
+1
View File
@@ -17,6 +17,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="System.Device.Gpio" Version="4.0.1" /> <PackageReference Include="System.Device.Gpio" Version="4.0.1" />
<PackageReference Include="Iot.Device.Bindings" Version="4.0.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+2
View File
@@ -104,6 +104,7 @@ public class LightsService
} }
public void Ping(CancellationToken cancellationToken = default) => SendRequest(_client.Ping, new Empty(), cancellationToken); public void Ping(CancellationToken cancellationToken = default) => SendRequest(_client.Ping, new Empty(), cancellationToken);
public void Disconnect(CancellationToken cancellationToken = default) => SendRequest(_client.Disconnect, new Empty(), cancellationToken);
public void Off(CancellationToken cancellationToken = default) => SendRequest(_client.SetOff, new Empty(), cancellationToken); public void Off(CancellationToken cancellationToken = default) => SendRequest(_client.SetOff, new Empty(), cancellationToken);
public void StaticColor(double brightness, Color color, CancellationToken cancellationToken = default) => SendRequest(_client.SetStaticColor, new StaticColorRequest public void StaticColor(double brightness, Color color, CancellationToken cancellationToken = default) => SendRequest(_client.SetStaticColor, new StaticColorRequest
{ {
@@ -274,6 +275,7 @@ public class LightsService
}, cancellationToken); }, cancellationToken);
public async Task PingAsync(CancellationToken cancellationToken = default) => await SendRequestAsync(_client.PingAsync, new Empty(), cancellationToken); public async Task PingAsync(CancellationToken cancellationToken = default) => await SendRequestAsync(_client.PingAsync, new Empty(), cancellationToken);
public async Task DisconnectAsync(CancellationToken cancellationToken = default) => await SendRequestAsync(_client.DisconnectAsync, new Empty(), cancellationToken);
public async Task OffAsync(CancellationToken cancellationToken = default) => await SendRequestAsync(_client.SetOffAsync, new Empty(), cancellationToken); public async Task OffAsync(CancellationToken cancellationToken = default) => await SendRequestAsync(_client.SetOffAsync, new Empty(), cancellationToken);
public async Task StaticColorAsync(double brightness, Color color, CancellationToken cancellationToken = default) => await SendRequestAsync(_client.SetStaticColorAsync, new StaticColorRequest public async Task StaticColorAsync(double brightness, Color color, CancellationToken cancellationToken = default) => await SendRequestAsync(_client.SetStaticColorAsync, new StaticColorRequest
{ {
@@ -9,8 +9,8 @@ public class TemperatureHumidityService : IDisposable
{ {
public static TemperatureHumidityServiceConfiguration Default => new TemperatureHumidityServiceConfiguration public static TemperatureHumidityServiceConfiguration Default => new TemperatureHumidityServiceConfiguration
{ {
Bus = 0, Bus = 6,
Address = 0x44 Address = 0x45
}; };
public int Bus { get; set; } public int Bus { get; set; }
@@ -54,7 +54,7 @@ public class TemperatureHumidityService : IDisposable
} }
} }
public async Task<(double temperature, double relativeHumidity)> MeasureAsync(int measurementsCount = 1, CancellationToken cancellationToken = default) public (double temperature, double relativeHumidity) Measure(int measurementsCount = 1, bool checkCrc = true, CancellationToken cancellationToken = default)
{ {
// В соответствии с даташитом на SHT45-AD1B-R2 псевдокод измерения с высокой точностью следующий: // В соответствии с даташитом на SHT45-AD1B-R2 псевдокод измерения с высокой точностью следующий:
// i2c_write(i2c_addr=0x44, tx_bytes=[0xFD]) // i2c_write(i2c_addr=0x44, tx_bytes=[0xFD])
@@ -90,19 +90,19 @@ public class TemperatureHumidityService : IDisposable
// Отправляем команду // Отправляем команду
_sensor.Write(command); _sensor.Write(command);
// 10 мс ожидания // 10 мс ожидания
await Task.Delay(10, cancellationToken); Task.Delay(10, cancellationToken);
// Читаем данные // Читаем данные
_sensor.Read(data); _sensor.Read(data);
// Распаковываем данные [2 * 8-bit T-data; 8-bit CRC; 2 * 8-bit RH-data; 8-bit CRC] // Распаковываем данные [2 * 8-bit T-data; 8-bit CRC; 2 * 8-bit RH-data; 8-bit CRC]
ushort temperatureTicks = BitConverter.ToUInt16(data.ToArray(), 0);
byte temperatureChecksum = data[2]; byte temperatureChecksum = data[2];
int relativeHumidityTicks = BitConverter.ToUInt16(data.ToArray(), 3);
byte relativeHumidityChecksum = data[5]; byte relativeHumidityChecksum = data[5];
ushort temperatureTicks = BitConverter.ToUInt16(data.Slice(0, 2));
int relativeHumidityTicks = BitConverter.ToUInt16(data.Slice(3, 2));
// Проверка по CRC // Проверка по CRC
if (!CheckCrc(data.Slice(0, 2), temperatureChecksum) || if (checkCrc && (!CheckCrc(data.Slice(0, 2), temperatureChecksum) ||
!CheckCrc(data.Slice(3, 2), relativeHumidityChecksum)) !CheckCrc(data.Slice(3, 2), relativeHumidityChecksum)))
{ {
_logger.LogWarning("Temperature and humidity sensor CRC error"); _logger.LogWarning("Temperature and humidity sensor CRC error");
continue; continue;
+1 -1
View File
@@ -2,7 +2,7 @@ LED_COUNT=9
LED_PIN=23 LED_PIN=23
GAMMA=2.2 GAMMA=2.2
TIMEOUT=5 TIMEOUT_SECONDS=300
IDLE_BRIGHTNESS=0.30 IDLE_BRIGHTNESS=0.30
IDLE_R=0 IDLE_R=0
+2 -1
View File
@@ -1 +1,2 @@
!.env !.env
venv
+9 -2
View File
@@ -34,7 +34,7 @@ LED_PIN_NUM = get_env_int("LED_PIN")
LED_PIN = getattr(board, f"D{LED_PIN_NUM}") LED_PIN = getattr(board, f"D{LED_PIN_NUM}")
GAMMA = get_env_float("GAMMA") GAMMA = get_env_float("GAMMA")
TIMEOUT = get_env_float("TIMEOUT") TIMEOUT_SECONDS = get_env_float("TIMEOUT_SECONDS")
IDLE_SPEED = get_env_float("IDLE_SPEED") IDLE_SPEED = get_env_float("IDLE_SPEED")
IDLE_BRIGHTNESS = get_env_float("IDLE_BRIGHTNESS") IDLE_BRIGHTNESS = get_env_float("IDLE_BRIGHTNESS")
@@ -579,7 +579,7 @@ class LightsDaemon(lights_pb2_grpc.LightsServicer):
def loop(self): def loop(self):
while self._running: while self._running:
with self._lock: with self._lock:
if self._control_mode and time.time() - self._last_ping > TIMEOUT: if self._control_mode and time.time() - self._last_ping > TIMEOUT_SECONDS:
self._control_mode = False self._control_mode = False
self._pixels.brightness = IDLE_BRIGHTNESS self._pixels.brightness = IDLE_BRIGHTNESS
self._animation = IdleAnimation() self._animation = IdleAnimation()
@@ -597,6 +597,13 @@ class LightsDaemon(lights_pb2_grpc.LightsServicer):
self._control_mode = True self._control_mode = True
self._last_ping = time.time() self._last_ping = time.time()
def Disconnect(self, request, context):
with self._lock:
self._control_mode = False
self._pixels.brightness = IDLE_BRIGHTNESS
self._animation = IdleAnimation()
return lights_pb2.Empty()
def Ping(self, request, context): def Ping(self, request, context):
self._update_last_ping() self._update_last_ping()
return lights_pb2.Empty() return lights_pb2.Empty()
File diff suppressed because one or more lines are too long
@@ -39,6 +39,11 @@ class LightsStub(object):
request_serializer=lights__pb2.Empty.SerializeToString, request_serializer=lights__pb2.Empty.SerializeToString,
response_deserializer=lights__pb2.Empty.FromString, response_deserializer=lights__pb2.Empty.FromString,
_registered_method=True) _registered_method=True)
self.Disconnect = channel.unary_unary(
'/GSS2.LightsControl.Lights/Disconnect',
request_serializer=lights__pb2.Empty.SerializeToString,
response_deserializer=lights__pb2.Empty.FromString,
_registered_method=True)
self.SetOff = channel.unary_unary( self.SetOff = channel.unary_unary(
'/GSS2.LightsControl.Lights/SetOff', '/GSS2.LightsControl.Lights/SetOff',
request_serializer=lights__pb2.Empty.SerializeToString, request_serializer=lights__pb2.Empty.SerializeToString,
@@ -145,6 +150,12 @@ class LightsServicer(object):
context.set_details('Method not implemented!') context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!') raise NotImplementedError('Method not implemented!')
def Disconnect(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def SetOff(self, request, context): def SetOff(self, request, context):
"""Missing associated documentation comment in .proto file.""" """Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED) context.set_code(grpc.StatusCode.UNIMPLEMENTED)
@@ -267,6 +278,11 @@ def add_LightsServicer_to_server(servicer, server):
request_deserializer=lights__pb2.Empty.FromString, request_deserializer=lights__pb2.Empty.FromString,
response_serializer=lights__pb2.Empty.SerializeToString, response_serializer=lights__pb2.Empty.SerializeToString,
), ),
'Disconnect': grpc.unary_unary_rpc_method_handler(
servicer.Disconnect,
request_deserializer=lights__pb2.Empty.FromString,
response_serializer=lights__pb2.Empty.SerializeToString,
),
'SetOff': grpc.unary_unary_rpc_method_handler( 'SetOff': grpc.unary_unary_rpc_method_handler(
servicer.SetOff, servicer.SetOff,
request_deserializer=lights__pb2.Empty.FromString, request_deserializer=lights__pb2.Empty.FromString,
@@ -400,6 +416,33 @@ class Lights(object):
metadata, metadata,
_registered_method=True) _registered_method=True)
@staticmethod
def Disconnect(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(
request,
target,
'/GSS2.LightsControl.Lights/Disconnect',
lights__pb2.Empty.SerializeToString,
lights__pb2.Empty.FromString,
options,
channel_credentials,
insecure,
call_credentials,
compression,
wait_for_ready,
timeout,
metadata,
_registered_method=True)
@staticmethod @staticmethod
def SetOff(request, def SetOff(request,
target, target,
+1
View File
@@ -6,6 +6,7 @@ package GSS2.LightsControl;
service Lights { service Lights {
rpc Ping (Empty) returns (Empty); rpc Ping (Empty) returns (Empty);
rpc Disconnect (Empty) returns (Empty);
rpc SetOff (Empty) returns (Empty); rpc SetOff (Empty) returns (Empty);
+4 -4
View File
@@ -26,9 +26,9 @@ public class Program
var configuration = serviceProvider.GetService<IConfiguration>(); var configuration = serviceProvider.GetService<IConfiguration>();
if (configuration is null) if (configuration is null)
throw new Exception("Cannot get configuration"); throw new Exception("Cannot get configuration");
var serviceConfiguration = configuration.GetValue<LightsService.LightsServiceConfiguration>("Lights"); var serviceConfiguration = configuration.GetSection("Hardware:Lights").Get<LightsService.LightsServiceConfiguration>();
if (serviceConfiguration is null) if (serviceConfiguration is null)
throw new InvalidConfigurationException("Cannot get configuration (Lights)"); throw new InvalidConfigurationException("Cannot get configuration (Hardware:Lights)");
var logger = serviceProvider.GetService<ILogger<LightsService>>(); var logger = serviceProvider.GetService<ILogger<LightsService>>();
if (logger is null) if (logger is null)
throw new Exception("Cannot get logger"); throw new Exception("Cannot get logger");
@@ -41,9 +41,9 @@ public class Program
var configuration = serviceProvider.GetService<IConfiguration>(); var configuration = serviceProvider.GetService<IConfiguration>();
if (configuration is null) if (configuration is null)
throw new Exception("Cannot get configuration"); throw new Exception("Cannot get configuration");
var serviceConfiguration = configuration.GetValue<TemperatureHumidityService.TemperatureHumidityServiceConfiguration>("TemperatureHumidity"); var serviceConfiguration = configuration.GetSection("Hardware:TemperatureHumidity").Get<TemperatureHumidityService.TemperatureHumidityServiceConfiguration>();
if (serviceConfiguration is null) if (serviceConfiguration is null)
throw new InvalidConfigurationException("Cannot get configuration (TemperatureHumidity)"); throw new InvalidConfigurationException("Cannot get configuration (Hardware:TemperatureHumidity)");
var logger = serviceProvider.GetService<ILogger<TemperatureHumidityService>>(); var logger = serviceProvider.GetService<ILogger<TemperatureHumidityService>>();
if (logger is null) if (logger is null)
throw new Exception("Cannot get logger"); throw new Exception("Cannot get logger");
+2 -6
View File
@@ -7,23 +7,19 @@ namespace GSS2.Test;
public class Worker( public class Worker(
ILogger<Worker> logger, ILogger<Worker> logger,
AmineContentCalibrationContext calibrationContext, AmineContentCalibrationContext calibrationContext,
LightsService lightsService, LightsService lightsService
TemperatureHumidityService temperatureHumidity
) : BackgroundService ) : BackgroundService
{ {
private readonly ILogger<Worker> _logger = logger; private readonly ILogger<Worker> _logger = logger;
private readonly AmineContentCalibrationContext _calibrationContext = calibrationContext; private readonly AmineContentCalibrationContext _calibrationContext = calibrationContext;
private readonly LightsService _lightsService = lightsService; private readonly LightsService _lightsService = lightsService;
private readonly TemperatureHumidityService _temperatureHumidity = temperatureHumidity;
protected override async Task ExecuteAsync(CancellationToken cancellationToken) protected override async Task ExecuteAsync(CancellationToken cancellationToken)
{ {
_ = _lightsService.Run(cancellationToken); _ = _lightsService.Run(cancellationToken);
await _lightsService.SnowfallAsync(0.3, 1, Color.Aqua, cancellationToken); _ = _lightsService.SnowfallAsync(0.3, 1, Color.Aqua, cancellationToken);
while (!cancellationToken.IsCancellationRequested) while (!cancellationToken.IsCancellationRequested)
{ {
var (temperature, humidity) = await _temperatureHumidity.MeasureAsync();
_logger.LogInformation("Temperature: {}, RelativeHumidity: {}", temperature, humidity);
await Task.Delay(5000); await Task.Delay(5000);
} }
} }
+3 -3
View File
@@ -23,11 +23,11 @@
"MaxUv365PwmDuty": 1.0 "MaxUv365PwmDuty": 1.0
}, },
"TemperatureHumidity": { "TemperatureHumidity": {
"Bus": 0, "Bus": 6,
"Address": 68 "Address": 69
}, },
"Lights": { "Lights": {
"ServerAddress": "localhost:50051" "ServerAddress": "http://127.0.0.1:50051"
} }
} }
} }