python - 将 Python 执行结果传输到 .NET Core
问题描述
我正在做一个物联网项目。该项目的目标是构建一个 iOT 鸟巢,我的运行 Raspbian OS (Linux) 的 Raspberry Pi 4 已经照顾好鸟儿。
尽管 .NET Core 支持 iOT,但缺少许多设备绑定,并且对 iOT 的支持尚未增长。每个人都在使用 Python 进行物联网编程,虽然很流行,但它没有任何好看的结构或冗长的语言
我的目的是收集
- 巢外环境温度
- 巢内环境温度
- 巢内湿度
- 巢中鸟的运动跟踪
- 控制用于加热巢穴的白炽灯泡
- 控制用于加湿巢穴的压电雾化器
- 使用 16x2 LCD 屏幕在巢上显示消息
我不是 Python 的粉丝,但我必须用它来读取传感器,因为它是唯一可用的解决方案。现在,一旦我得到结果,我就不想再使用 Python。因为我有更多的步骤要做
- 将传感器的读数保存到 MySQL DB
- 处理结果
- 创建用于控制 GPIO 引脚的 API 端点
- 创建一个 MVC 应用程序以显示仪表板
对于这些后处理,我从不想使用 Python。我想使用 .NET Core。我想实现一种机制,其中 .NET 代码将告诉 Python 该做什么并与传感器进行通信。
我目前已经实现了它 - 使用将标准输出从 linux shell 重定向到 dotnet .NET 并且它工作正常。我在 Python 上用 JSON 编码数据并在控制台上打印它。然后 C# 将调用 process 并重定向 stdio 以使用 JSON 并对其进行反序列化。
但这是更好的方法吗?
这对我来说适用于大多数情况,例如读取温度、湿度等。但是要控制 LCD 显示,感觉很难告诉 python 文件使用 C# 代码中的命令参数做什么,因为我需要处理很多 switch case在 Python 文件中区分不同 LCD 渲染的不同参数,如清除、向左移动、向右移动等。
我可以使用任何更好的方法吗?
这是我用来从 Python 脚本获取结果的代码
using DigitalNest.DataModels;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Unosquare.RaspberryIO;
using Unosquare.RaspberryIO.Abstractions;
using Unosquare.WiringPi;
namespace DigitalNest
{
public class Program
{
public static IConfigurationRoot configuration;
private static Sensors sensors;
private static string connectionString;
private static void ConfigureServices(IServiceCollection serviceCollection)
{
configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
.AddJsonFile("appsettings.json", false)
.Build();
serviceCollection.AddSingleton<IConfigurationRoot>(configuration);
var sensors = new Sensors();
configuration.Bind("Sensors", sensors);
serviceCollection.AddSingleton(sensors);
}
public Program(Sensors sensor)
{
sensors = sensor;
connectionString = configuration.GetConnectionString("DigitalNestDB");
}
private static void RecordTemprature(string temprature)
{
var bufferQuery = $"SELECT COUNT(*) FROM Tempratures";
var count = SqlHelper.Query<int>(bufferQuery, connectionString).FirstOrDefault();
if (count > sensors.DHT.TempBuffer)
{
var truncateQuery = $"DELETE FROM Tempratures WHERE `Event` IS NOT NULL ORDER BY `Event` ASC LIMIT 1";
SqlHelper.Query<int>(truncateQuery, connectionString);
}
else
{
var temp = new Temp
{
Temprature = temprature,
Event = DateTime.UtcNow
};
SqlHelper.Insert<Temp>(temp, connectionString);
}
}
private static void RecordHumidity(string humidity)
{
var bufferQuery = $"SELECT COUNT(*) FROM Humidities";
var count = SqlHelper.Query<int>(bufferQuery, connectionString).FirstOrDefault();
if (count > sensors.DHT.HumidityBuffer)
{
var truncateQuery = $"DELETE FROM Humidities WHERE `Event` IS NOT NULL ORDER BY `Event` ASC LIMIT 1";
SqlHelper.Query<int>(truncateQuery, connectionString);
}
else
{
var humid = new Humid
{
Humidity = humidity,
Event = DateTime.UtcNow
};
SqlHelper.Insert<Humid>(humid, connectionString);
}
}
private static void RecordMotion(bool isMotion)
{
var bufferQuery = $"SELECT COUNT(*) FROM Motion";
var count = SqlHelper.Query<int>(bufferQuery, connectionString).FirstOrDefault();
if (count > sensors.PIR.MotionBuffer)
{
var truncateQuery = $"DELETE FROM Motion WHERE `Event` IS NOT NULL ORDER BY `Event` ASC LIMIT 1";
SqlHelper.Query<int>(truncateQuery, connectionString);
}
else
{
var motion = new Motion
{
IsMotion = isMotion,
Event = DateTime.UtcNow
};
SqlHelper.Insert<Motion>(motion, connectionString);
}
}
private static void ReadDHTSensor()
{
while (true)
{
try
{
var stdio = sensors.DHT.Bash.BashExecute();
var output = JsonConvert.DeserializeObject<DHTData>(stdio);
RecordTemprature(output.Temprature);
RecordHumidity(output.Humidity);
Console.WriteLine(stdio);
Thread.Sleep(sensors.DHT.RefreshRate);
}
catch (Exception ex)
{
Console.WriteLine("DHT Error");
Thread.Sleep(sensors.DHT.RefreshRate);
}
}
}
private static void ReadPIRSensor()
{
while (true)
{
try
{
var stdio = sensors.PIR.Bash.BashExecute();
Console.WriteLine($"{stdio}");
var output = JsonConvert.DeserializeObject<PIRData>(stdio);
RecordMotion(output.Motion);
Console.WriteLine(stdio);
Thread.Sleep(sensors.PIR.RefreshRate);
}
catch (Exception ex)
{
Console.WriteLine("PIR Error");
Thread.Sleep(sensors.PIR.RefreshRate);
}
}
}
private static void GenerateUltrasonicSound()
{
while (true)
{
try
{
Console.WriteLine("Sounding..");
var passiveBuzzer = (GpioPin)Pi.Gpio[BcmPin.Gpio26];
passiveBuzzer.SoftToneFrequency = sensors.UltrasonicBuzzer.AudioFrequency;
Thread.Sleep(sensors.UltrasonicBuzzer.RefreshRate);
passiveBuzzer.SoftToneFrequency = 0;
}
catch (Exception ex)
{
Console.WriteLine("Ultrasonic PiezoBuzzer Error - " + ex.ToString());
Thread.Sleep(sensors.UltrasonicBuzzer.RefreshRate);
}
}
}
private static void Main(string[] args)
{
ServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
sensors = serviceProvider.GetService<Sensors>();
connectionString = configuration.GetConnectionString("DigitalNestDB");
Pi.Init<BootstrapWiringPi>();
Parallel.Invoke(
() => ReadPIRSensor(),
() => ReadDHTSensor(),
() => GenerateUltrasonicSound()
);
while (true)
{
}
}
}
}
这是 BashExecute() 辅助函数
public static string BashExecute(this string cmd)
{
var escapedArgs = cmd.Replace("\"", "\\\"");
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
FileName = "/bin/bash",
Arguments = $"-c \"{escapedArgs}\"",
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true,
}
};
process.Start();
string result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
return result;
}
解决方案
推荐阅读
- android - 了解 View.drawableStateChanged
- javascript - 仅使用 Javascript 动态填充谷歌图表
- istio - istio 跟踪网络请求并查找故障点
- node.js - Flutter Web 状态和使用 Flutter 的服务器端解决方案
- r - 如何将分类列表应用于 excel 或 R 中的大型数据集
- python - 匹配一个单词中的多个双字符 - Python regex
- kotlin - 具有 Kotlin 类型推断的反应器因 flatMapMany(Flux::fromIterable)而失败
- c++ - 调用操作符方法和调用子类中没有实现的父类的其他方法有什么区别?
- sql-server - Spark - 使用 com.microsoft.azure 从 SQL Server 读取
- javascript - 将文件转换为模块时类不存在