forked from amkovkov/GranuSightSoftware2
feat: минорые изменения после тестирования
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.0" />
|
||||
<PackageReference Include="System.Device.Gpio" Version="4.0.1" />
|
||||
<PackageReference Include="Iot.Device.Bindings" Version="4.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -104,6 +104,7 @@ public class LightsService
|
||||
}
|
||||
|
||||
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 StaticColor(double brightness, Color color, CancellationToken cancellationToken = default) => SendRequest(_client.SetStaticColor, new StaticColorRequest
|
||||
{
|
||||
@@ -274,6 +275,7 @@ public class LightsService
|
||||
}, 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 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
|
||||
{
|
||||
Bus = 0,
|
||||
Address = 0x44
|
||||
Bus = 6,
|
||||
Address = 0x45
|
||||
};
|
||||
|
||||
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 псевдокод измерения с высокой точностью следующий:
|
||||
// i2c_write(i2c_addr=0x44, tx_bytes=[0xFD])
|
||||
@@ -90,19 +90,19 @@ public class TemperatureHumidityService : IDisposable
|
||||
// Отправляем команду
|
||||
_sensor.Write(command);
|
||||
// 10 мс ожидания
|
||||
await Task.Delay(10, cancellationToken);
|
||||
Task.Delay(10, cancellationToken);
|
||||
// Читаем данные
|
||||
_sensor.Read(data);
|
||||
|
||||
// Распаковываем данные [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];
|
||||
int relativeHumidityTicks = BitConverter.ToUInt16(data.ToArray(), 3);
|
||||
byte relativeHumidityChecksum = data[5];
|
||||
ushort temperatureTicks = BitConverter.ToUInt16(data.Slice(0, 2));
|
||||
int relativeHumidityTicks = BitConverter.ToUInt16(data.Slice(3, 2));
|
||||
|
||||
// Проверка по CRC
|
||||
if (!CheckCrc(data.Slice(0, 2), temperatureChecksum) ||
|
||||
!CheckCrc(data.Slice(3, 2), relativeHumidityChecksum))
|
||||
if (checkCrc && (!CheckCrc(data.Slice(0, 2), temperatureChecksum) ||
|
||||
!CheckCrc(data.Slice(3, 2), relativeHumidityChecksum)))
|
||||
{
|
||||
_logger.LogWarning("Temperature and humidity sensor CRC error");
|
||||
continue;
|
||||
|
||||
@@ -2,7 +2,7 @@ LED_COUNT=9
|
||||
LED_PIN=23
|
||||
|
||||
GAMMA=2.2
|
||||
TIMEOUT=5
|
||||
TIMEOUT_SECONDS=300
|
||||
|
||||
IDLE_BRIGHTNESS=0.30
|
||||
IDLE_R=0
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
!.env
|
||||
!.env
|
||||
venv
|
||||
@@ -34,7 +34,7 @@ LED_PIN_NUM = get_env_int("LED_PIN")
|
||||
LED_PIN = getattr(board, f"D{LED_PIN_NUM}")
|
||||
|
||||
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_BRIGHTNESS = get_env_float("IDLE_BRIGHTNESS")
|
||||
@@ -579,7 +579,7 @@ class LightsDaemon(lights_pb2_grpc.LightsServicer):
|
||||
def loop(self):
|
||||
while self._running:
|
||||
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._pixels.brightness = IDLE_BRIGHTNESS
|
||||
self._animation = IdleAnimation()
|
||||
@@ -597,6 +597,13 @@ class LightsDaemon(lights_pb2_grpc.LightsServicer):
|
||||
self._control_mode = True
|
||||
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):
|
||||
self._update_last_ping()
|
||||
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,
|
||||
response_deserializer=lights__pb2.Empty.FromString,
|
||||
_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(
|
||||
'/GSS2.LightsControl.Lights/SetOff',
|
||||
request_serializer=lights__pb2.Empty.SerializeToString,
|
||||
@@ -145,6 +150,12 @@ class LightsServicer(object):
|
||||
context.set_details('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):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
@@ -267,6 +278,11 @@ def add_LightsServicer_to_server(servicer, server):
|
||||
request_deserializer=lights__pb2.Empty.FromString,
|
||||
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(
|
||||
servicer.SetOff,
|
||||
request_deserializer=lights__pb2.Empty.FromString,
|
||||
@@ -400,6 +416,33 @@ class Lights(object):
|
||||
metadata,
|
||||
_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
|
||||
def SetOff(request,
|
||||
target,
|
||||
|
||||
@@ -6,6 +6,7 @@ package GSS2.LightsControl;
|
||||
|
||||
service Lights {
|
||||
rpc Ping (Empty) returns (Empty);
|
||||
rpc Disconnect (Empty) returns (Empty);
|
||||
|
||||
rpc SetOff (Empty) returns (Empty);
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ public class Program
|
||||
var configuration = serviceProvider.GetService<IConfiguration>();
|
||||
if (configuration is null)
|
||||
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)
|
||||
throw new InvalidConfigurationException("Cannot get configuration (Lights)");
|
||||
throw new InvalidConfigurationException("Cannot get configuration (Hardware:Lights)");
|
||||
var logger = serviceProvider.GetService<ILogger<LightsService>>();
|
||||
if (logger is null)
|
||||
throw new Exception("Cannot get logger");
|
||||
@@ -41,9 +41,9 @@ public class Program
|
||||
var configuration = serviceProvider.GetService<IConfiguration>();
|
||||
if (configuration is null)
|
||||
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)
|
||||
throw new InvalidConfigurationException("Cannot get configuration (TemperatureHumidity)");
|
||||
throw new InvalidConfigurationException("Cannot get configuration (Hardware:TemperatureHumidity)");
|
||||
var logger = serviceProvider.GetService<ILogger<TemperatureHumidityService>>();
|
||||
if (logger is null)
|
||||
throw new Exception("Cannot get logger");
|
||||
|
||||
+2
-6
@@ -7,23 +7,19 @@ namespace GSS2.Test;
|
||||
public class Worker(
|
||||
ILogger<Worker> logger,
|
||||
AmineContentCalibrationContext calibrationContext,
|
||||
LightsService lightsService,
|
||||
TemperatureHumidityService temperatureHumidity
|
||||
LightsService lightsService
|
||||
) : BackgroundService
|
||||
{
|
||||
private readonly ILogger<Worker> _logger = logger;
|
||||
private readonly AmineContentCalibrationContext _calibrationContext = calibrationContext;
|
||||
private readonly LightsService _lightsService = lightsService;
|
||||
private readonly TemperatureHumidityService _temperatureHumidity = temperatureHumidity;
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_ = _lightsService.Run(cancellationToken);
|
||||
await _lightsService.SnowfallAsync(0.3, 1, Color.Aqua, cancellationToken);
|
||||
_ = _lightsService.SnowfallAsync(0.3, 1, Color.Aqua, cancellationToken);
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var (temperature, humidity) = await _temperatureHumidity.MeasureAsync();
|
||||
_logger.LogInformation("Temperature: {}, RelativeHumidity: {}", temperature, humidity);
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
"MaxUv365PwmDuty": 1.0
|
||||
},
|
||||
"TemperatureHumidity": {
|
||||
"Bus": 0,
|
||||
"Address": 68
|
||||
"Bus": 6,
|
||||
"Address": 69
|
||||
},
|
||||
"Lights": {
|
||||
"ServerAddress": "localhost:50051"
|
||||
"ServerAddress": "http://127.0.0.1:50051"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user