首页 > 解决方案 > 从 javascript 到 C# 的函数解码器

问题描述

我有一个 LHT65 传感器,它发送一个编码的有效载荷,我在 javascript 中找到了这段代码:

https://gist.github.com/koenvervloesem/c9dca322bd25a98dd042324469d0081d

// Source: http://www.dragino.com/downloads/downloads/LHT65/UserManual/LHT65_Temperature_Humidity_Sensor_UserManual_v1.3.pdf
function Decoder(bytes, port) {
    // Decode an uplink message from a buffer
    // (array) of bytes to an object of fields.
    var value = (bytes[0] << 8 | bytes[1]) & 0x3FFF;
    var batV = value / 1000; //Battery,units:V

    value = bytes[2] << 8 | bytes[3];
    if (bytes[2] & 0x80) {
        value |= 0xFFFF0000;
    }
    var temp_SHT = (value / 100).toFixed(2); //SHT20,temperature,units:°C

    value = bytes[4] << 8 | bytes[5];
    var hum_SHT = (value / 10).toFixed(1); //SHT20,Humidity,units:%

    value = bytes[7] << 8 | bytes[8];
    if (bytes[7] & 0x80) {
        value |= 0xFFFF0000;
    }
    var temp_ds = (value / 100).toFixed(2); //DS18B20,temperature,units:°C

    return {
        BatV: batV,
        TempC_DS: temp_ds,
        TempC_SHT: temp_SHT,
        Hum_SHT: hum_SHT
    };
}

但是我需要在 C# 中构建解码器,所以我尝试了这个:

namespace SensorDecoderModule.Classes
{
    using System;
    using Newtonsoft.Json.Linq;
    using Newtonsoft.Json;

    public class Lht65Info
    {
        public float BatV {get; set;}
        public float  TempC_DS {get; set;}
        public float temp_SHT {get; set;}
        public float Hum_SHT {get; set;}

    }

    internal static partial class LoraDecoders
    {
        private static string Lht65_Sensor_Decoder(string devEUI, byte[] payload, byte fport)
        {
            var value = (payload[0] << 8 | payload[1]) & 0x3FFF;
            var batV = value / 1000; //Battery,units:V

            value = payload[2] << 8 | payload[3];
            if (payload[2] & 0x80) {
                value |= 0xFFFF0000;
            }
            var temp_SHT = (value / 100).toFixed(2); //SHT20,temperature,units:°C

            value = payload[4] << 8 | payload[5];
            var hum_SHT = (value / 10).toFixed(1); //SHT20,Humidity,units:%

            value = payload[7] << 8 | payload[8];
            if (payload[7] & 0x80) {
                value |= 0xFFFF0000;
            }
            var temp_ds = (value / 100).toFixed(2); //DS18B20,temperature,units:°C

            Lht65Info info = new  Lht65Info(){
               BatV = batV,
               TempC_DS = temp_ds,
               TempC_SHT = temp_SHT,
               Hum_SHT = hum_SHT
            };

            return JsonConvert.SerializeObject(info, Formatting.Indented);
    
        }
    }
}

但是我有几个错误:

Decoders\Lht65_Decoder.cs(26,17): error CS0029: Cannot implicitly convert type 'int' to 'bool' [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(27,17): error CS0266: Cannot implicitly convert type 'uint' to 'int'. An explicit conversion exists (are you missing a cast?) [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(29,42): error CS1061: 'int' does not contain a definition for 'toFixed' and no accessible extension method 'toFixed' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(32,40): error CS1061: 'int' does not contain a definition for 'toFixed' and no accessible extension method 'toFixed' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(35,17): error CS0029: Cannot implicitly convert type 'int' to 'bool' [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(36,17): error CS0266: Cannot implicitly convert type 'uint' to 'int'. An explicit conversion exists (are you missing a cast?) [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(38,41): error CS1061: 'int' does not contain a definition for 'toFixed' and no accessible extension method 'toFixed' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]
Decoders\Lht65_Decoder.cs(43,16): error CS0117: 'Lht65Info' does not contain a definition for 'TempC_SHT' [C:\Users\xx\Downloads\Repos\iotedge-lorawan-starterkit-decoders\DecoderCollection\SensorDecoderModule.csproj]

标签: javascriptc#jsonbyte

解决方案


C# 与 javascript 不同,因此您不能只是复制和粘贴 javascript 代码。

Javascript 有一种number用于所有目的的类型(对应于 C#double类型)。因此,当您在 javascipt 中执行此操作时:

var batV = value / 1000;

结果是小数。但是,当您在 C# 中执行相同操作时(valueint 在哪里)-您会int返回,因此结果会向下舍入。所以应该是:

var batV = value / 1000f;

强行batV成为一个float。这同样适用于您拥有的其他整数除法(value / 100等)。

然后在 javascript 中,零(或 null\undefined)的数字是“假的”,并且数字可以在 if 语句中用作条件。C# 没有这个 - 你在 if 语句中使用的应该是布尔类型。所以而不是:

if (payload[2] & 0x80)

你需要

if ((payload[2] & 0x80) != 0)

那么,这

 value |= 0xFFFF0000;

不会按原样工作,因为value它是 int,但右侧的 costant 不适合int并且实际上是uint(无符号整数)。由于您不关心实际值,而只关心二进制表示 - 您可以将其转换为 int 并溢出:

value |= unchecked((int) 0xFFFF0000);

没有toFixed功能,您可以使用以下方法执行相同操作:

var temp_SHT = (value / 100f).ToString("F2");

ToStringtoFixed在 javascript 中)返回字符串,而您的TempC_DSetc 属性是 type float。因此,您要么需要删除对字符串的转换,要么将所述属性设为 type string


推荐阅读