diff --git a/2jciebu.cs b/2jciebu.cs
index a820afe..2a1f313 100644
--- a/2jciebu.cs
+++ b/2jciebu.cs
@@ -1,32 +1,116 @@
namespace SensorReadings;
+///
+/// 表示 OMRON 2JCIE-BU 传感器的单条读数。
+///
internal sealed class Jciebu2
{
+ ///
+ /// 采样时间戳(字符串格式)。
+ ///
public string Ts { get; set; } = string.Empty;
+ ///
+ /// 采样位置或设备位置标识。
+ ///
public string Location { get; set; } = string.Empty;
+ ///
+ /// 温度(摄氏度)。
+ ///
public double TemperatureC { get; set; }
+ ///
+ /// 相对湿度(%RH)。
+ ///
public double HumidityRh { get; set; }
+ ///
+ /// 环境光照度。
+ ///
public double AmbientLight { get; set; }
+ ///
+ /// 气压(hPa)。
+ ///
public double PressureHpa { get; set; }
+ ///
+ /// 噪声(dB)。
+ ///
public double NoiseDb { get; set; }
+ ///
+ /// 总挥发性有机物(eTVOC,ppb)。
+ ///
public double EtvocPpb { get; set; }
+ ///
+ /// 等效二氧化碳浓度(eCO2,ppm)。
+ ///
public double Eco2Ppm { get; set; }
+ ///
+ /// 舒适度指数。
+ ///
public double DiscomfortIndex { get; set; }
+ ///
+ /// 中暑指数。
+ ///
public double HeatstrokeIndex { get; set; }
+ ///
+ /// 振动信息(设备原始标记值)。
+ ///
public int VibrationInfo { get; set; }
+ ///
+ /// 振动 SI 值。
+ ///
public double SiValue { get; set; }
+ ///
+ /// 峰值加速度(PGA,gal)。
+ ///
public double PgaGal { get; set; }
+ ///
+ /// 地震烈度(计算值)。
+ ///
public double SeismicIntensity { get; set; }
+ ///
+ /// 温度告警标记。
+ ///
public int TemperatureFlag { get; set; }
+ ///
+ /// 湿度告警标记。
+ ///
public int HumidityFlag { get; set; }
+ ///
+ /// 光照告警标记。
+ ///
public int AmbientLightFlag { get; set; }
+ ///
+ /// 气压告警标记。
+ ///
public int PressureFlag { get; set; }
+ ///
+ /// 噪声告警标记。
+ ///
public int NoiseFlag { get; set; }
+ ///
+ /// eTVOC 告警标记。
+ ///
public int EtvocFlag { get; set; }
+ ///
+ /// eCO2 告警标记。
+ ///
public int Eco2Flag { get; set; }
+ ///
+ /// 舒适度告警标记。
+ ///
public int DiscomfortFlag { get; set; }
+ ///
+ /// 中暑告警标记。
+ ///
public int HeatstrokeFlag { get; set; }
+ ///
+ /// SI 告警标记。
+ ///
public int SiFlag { get; set; }
+ ///
+ /// PGA 告警标记。
+ ///
public int PgaFlag { get; set; }
+ ///
+ /// 地震烈度告警标记。
+ ///
public int SeismicIntensityFlag { get; set; }
}
diff --git a/Program.cs b/Program.cs
index a2f0e52..8219e09 100644
--- a/Program.cs
+++ b/Program.cs
@@ -17,6 +17,11 @@
private static readonly string ODataToken = GetEnv("ODATA_TOKEN", string.Empty).Trim();
private static readonly double TimeoutSeconds = GetEnvDouble("ODATA_TIMEOUT_S", 10);
+ ///
+ /// 程序入口,读取最新传感器数据并可选上报到 OData。
+ ///
+ /// 命令行参数。
+ /// 进程退出码。
private static int Main(string[] args)
{
try
@@ -47,6 +52,11 @@
}
}
+ ///
+ /// 将传感器数据发送到配置的 OData 端点。
+ ///
+ /// 要发送的传感器数据。
+ /// HTTP 状态码与响应内容。
private static async Task<(int StatusCode, string Body)> PostODataAsync(Jciebu2 payload)
{
using var client = new HttpClient
@@ -69,6 +79,13 @@
return ((int)resp.StatusCode, body);
}
+ ///
+ /// 从串口设备读取最新数据,并统一时间戳与位置字段。
+ ///
+ /// 串口设备路径。
+ /// 位置标识,若为空则使用默认值。
+ /// 是否开启读数时的指示灯。
+ /// 解析后的传感器数据。
private static Jciebu2 GetLatestReading(string port, string? location, bool led)
{
using var serial = new SerialPort(port, 115200, Parity.None, 8, StopBits.One)
@@ -138,6 +155,11 @@
}
}
+ ///
+ /// 将指令附加 CRC 后写入串口。
+ ///
+ /// 串口实例。
+ /// 原始指令字节。
private static void WriteWithCrc(SerialPort serial, byte[] command)
{
var crc = CalcCrc(command);
@@ -147,6 +169,12 @@
serial.Write(buf, 0, buf.Length);
}
+ ///
+ /// 从串口读取可用字节,直到缓冲不再增长或超时。
+ ///
+ /// 串口实例。
+ /// 读取超时时间。
+ /// 读取到的字节数组。
private static byte[] ReadAvailable(SerialPort serial, TimeSpan timeout)
{
var deadline = DateTime.UtcNow + timeout;
@@ -178,6 +206,11 @@
return buffer.ToArray();
}
+ ///
+ /// 解析“latest data long”响应为传感器数据。
+ ///
+ /// 设备返回的原始数据。
+ /// 解析后的传感器数据。
private static Jciebu2 ParseLatestDataLong(byte[] data)
{
if (data.Length < 56)
@@ -215,6 +248,11 @@
};
}
+ ///
+ /// 计算给定缓冲区的 CRC-16(Modbus)。
+ ///
+ /// 输入缓冲区。
+ /// CRC 字节(低位在前)。
private static byte[] CalcCrc(byte[] buf)
{
var crc = 0xFFFF;
@@ -237,24 +275,54 @@
return new[] { crcL, crcH };
}
+ ///
+ /// 从缓冲区读取无符号 16 位小端值。
+ ///
+ /// 数据缓冲区。
+ /// 起始偏移。
+ /// 读取到的数值。
private static ushort U16Le(byte[] data, int offset) =>
(ushort)(data[offset] | (data[offset + 1] << 8));
+ ///
+ /// 从缓冲区读取有符号 16 位小端值。
+ ///
+ /// 数据缓冲区。
+ /// 起始偏移。
+ /// 读取到的数值。
private static short S16Le(byte[] data, int offset) =>
(short)(data[offset] | (data[offset + 1] << 8));
+ ///
+ /// 从缓冲区读取无符号 32 位小端值。
+ ///
+ /// 数据缓冲区。
+ /// 起始偏移。
+ /// 读取到的数值。
private static uint U32Le(byte[] data, int offset) =>
(uint)(data[offset]
| (data[offset + 1] << 8)
| (data[offset + 2] << 16)
| (data[offset + 3] << 24));
+ ///
+ /// 读取环境变量,未设置或为空时返回默认值。
+ ///
+ /// 环境变量名。
+ /// 默认值。
+ /// 环境变量值或默认值。
private static string GetEnv(string name, string defaultValue)
{
var value = Environment.GetEnvironmentVariable(name);
return string.IsNullOrEmpty(value) ? defaultValue : value;
}
+ ///
+ /// 读取环境变量为 double(InvariantCulture),失败则返回默认值。
+ ///
+ /// 环境变量名。
+ /// 默认值。
+ /// 解析结果或默认值。
private static double GetEnvDouble(string name, double defaultValue)
{
var value = Environment.GetEnvironmentVariable(name);
@@ -263,6 +331,12 @@
: defaultValue;
}
+ ///
+ /// 判断参数列表中是否包含指定开关。
+ ///
+ /// 命令行参数。
+ /// 要查找的参数名。
+ /// 存在则为 true。
private static bool HasArg(string[] args, string name)
{
foreach (var arg in args)