跳到主要内容

脚本常见问题

提示

通过自定义脚本,可快速适配业务模型,比如各大云平台的Iot物模型

欢迎大家投稿平台适配案例

一、脚本示例

变量脚本(mqtt/kafka等)


//变量脚本动态设置传输实体的Demo
//只传输变量名称,变量值,变量在线状态,变量值改变时间
public class DemoScript:IDynamicModel
{
public IEnumerable<dynamic> GetList(IEnumerable<object> datas)
{
List<DemoData> demoDatas = new List<DemoData>();
foreach (var v in datas)
{
var data=(VariableData)v;
DemoData demoData = new DemoData();
demoData.Value = data.Value;
demoData.Name = data.Name;
demoData.IsOnline = data.IsOnline;
demoData.ChangeTime = data.ChangeTime;
demoDatas.Add(demoData);
}
return demoDatas;
}
}
public class DemoData
{
public string Name { get; set; }
public bool IsOnline { get; set; }
public object Value { get; set; }
public DateTime ChangeTime { get; set; }
}

二、适配 ThingsBoard 脚本

对应文档:ThingsBoard

设备属性脚本

using TouchSocket.Core;
public class ThingsBoardDeviceScript : IDynamicModel
{
public IEnumerable<dynamic> GetList(IEnumerable<object> datas)
{
Dictionary<string, Dictionary<string, object>>
dict = new Dictionary<string, Dictionary<string, object>>
();
foreach (var v in datas)
{
var data = (DeviceBasicData)v;
Dictionary<string, object> demoData = new Dictionary<string, object>
{
{ nameof(Device.Description), data.Description },
{ nameof(DeviceBasicData.ActiveTime), data.ActiveTime },
{ nameof(DeviceBasicData.DeviceStatus), data.DeviceStatus.ToString() },
{ nameof(DeviceBasicData.LastErrorMessage), data.LastErrorMessage },
{ nameof(DeviceBasicData.PluginName), data.PluginName },
{ nameof(DeviceBasicData.Remark1), data.Remark1 },
{ nameof(DeviceBasicData.Remark2), data.Remark2 },
{ nameof(DeviceBasicData.Remark3), data.Remark3 },
{ nameof(DeviceBasicData.Remark4), data.Remark4 },
{ nameof(DeviceBasicData.Remark5), data.Remark5 }
};

dict.AddOrUpdate(data.Name, demoData);
}
return new List<dynamic>() { dict };
}
}


变量脚本


using ThingsGateway.Foundation;

using TouchSocket.Core;

public class ThingsBoardVariableScript : IDynamicModel
{
public IEnumerable<dynamic> GetList(IEnumerable<object> datas)
{
var dict = new Dictionary<string, List<ThingsBoardValue>>();
// 对输入列表进行分组,根据 DeviceName 属性分组
var groups = datas.Where(a => !string.IsNullOrEmpty(((VariableData)a).DeviceName)).GroupBy(a => ((VariableData)a).DeviceName, a => ((VariableData)a));
// 遍历每一个分组
foreach (var group in groups)
{
var data = group.GroupBy(a => a.CollectTime);
List<ThingsBoardValue> thingsBoardValues = new();
foreach (var item in data)
{
ThingsBoardValue thingsBoardValue = new();
thingsBoardValue.ts = item.Key.DateTimeToUnixTimestamp();
foreach (var tag in item)
{
thingsBoardValue.values.AddOrUpdate(tag.Name, tag.Value);
}
thingsBoardValues.Add(thingsBoardValue);
}

dict.AddOrUpdate(group.Key, thingsBoardValues);

}
return new List<dynamic>() { dict };
}
}

public class ThingsBoardValue
{
public long ts { get; set; }
public Dictionary<string, object> values { get; set; } = new();
}


传输主题

变量Topic 填入 v1/gateway/telemetry

设备Topic 填入 v1/gateway/attributes

RpcTopic 天然 v1/gateway/rpc

变量列表上传 填入 false

设备状态列表上传 填入 false

三、适配阿里云物模型脚本

对应文档:阿里云设备属性上报

变量脚本


//一个适配阿里云IOT的变量脚本demo


public class AliYunIotScript:IDynamicModel
{
public IEnumerable<dynamic> GetList(IEnumerable<object> datas)
{
List<AliYunIot> aliYunIots = new();
// 对输入列表进行分组,根据 Remark1属性分组
var groups = datas.Where(a => !string.IsNullOrEmpty(((VariableData)a).Remark1)).GroupBy(a => ((VariableData)a).Remark1,a=> ((VariableData)a));
// 遍历每一个分组
foreach (var item in groups)
{
var requestId = Yitter.IdGenerator.YitIdHelper.NextId();
var iotId = item.Key; //Remark1自定义为设备Id
var productKey = item.FirstOrDefault(a => !string.IsNullOrEmpty(a.Remark2))?.Remark2;//Remark2自定义为产品Id
var deviceName = item.FirstOrDefault(a => !string.IsNullOrEmpty(a.Remark3))?.Remark3;//Remark3自定义为设备名称
AliYunIot aliYunIot = new();
aliYunIot.iotId = iotId;
aliYunIot.requestId = requestId.ToString();
aliYunIot.deviceName = deviceName;
aliYunIot.productKey = productKey;
// 遍历分组内的每一个元素
foreach (var varItem in item)
{

// 设置采集时间,并转换为 Unix 时间戳
// 设置值
var data = new Property() { value = varItem.Value, time = new DateTimeOffset(varItem.CollectTime).ToUnixTimeSeconds() };
// 以 变量名称 作为键,将新对象添加到分组的 属性 中
aliYunIot.items.Add(varItem.Name, data);

}
aliYunIots.Add(aliYunIot);
}
return aliYunIots;
}


}
public class AliYunIot
{
public string iotId { get; set; }
public string requestId { get; set; }
public string productKey { get; set; }
public string deviceName { get; set; }
public Dictionary<string, Property> items { get; set; } = new();
}

public class Property
{
public object value { get; set; }
public long time { get; set; }
}



传输主题

变量Topic 填入 /${productKey}/${deviceName}/thing/event/property/post

四、数据库脚本



//using SqlSugar;

//using ThingsGateway;
//using ThingsGateway.Foundation;
//using ThingsGateway.NewLife.Extension;
//using ThingsGateway.Plugin.DB;
//using ThingsGateway.Plugin.SqlDB;

//public class TestHistorySQL : IDynamicSQL
//{

// /// <summary>
// /// 获取新的表实体List
// /// </summary>
// /// <returns></returns>
// public IEnumerable<dynamic> GetList(IEnumerable<object> datas)
// {
// var sqlHistoryValues = datas.Cast<SQLHistoryValue>().OrderByDescending(a => a.CollectTime).DistinctBy(a => a.Name);
// List<HistoryModel1> demoDatas = new List<HistoryModel1>();
// HistoryModel1 demoData = new HistoryModel1();
// demoData.IsOnline = !sqlHistoryValues.Any(a => !a.IsOnline);
// demoData.CreateTime = DateTime.Now;
// var dict = sqlHistoryValues.ToDictionary(a => a.Name);
// demoData.Temp1 = dict["Device1_Temp1"].Value;
// demoData.Temp2 = dict["Device1_Temp2"].Value;
// demoData.Temp3 = dict["Device1_Temp3"].Value;
// demoDatas.Add(demoData);
// return demoDatas;
// }

// /// <summary>
// /// 获取新的表实体
// /// </summary>
// /// <returns></returns>
// public Type GetModelType()
// {
// return typeof(HistoryModel1);
// }

// [SplitTable(SplitType.Month)]//(自带分表支持 年、季、月、周、日)
// [SugarTable("HistoryModel1_{year}{month}{day}", TableDescription = "设备采集历史表")]//3个变量必须要有
// [SugarIndex("index_CreateTime", nameof(SQLHistoryValue.CreateTime), OrderByType.Desc)]
// public class HistoryModel1
// {
// [SplitField] //分表字段 在插入的时候会根据这个字段插入哪个表,在更新删除的时候用这个字段找出相关表
// public DateTime CreateTime { get; set; }

// ///<summary>
// ///是否在线
// ///</summary>
// [SugarColumn(ColumnDescription = "是否在线")]
// public bool IsOnline { get; set; }

// public string Temp1 { get; set; }

// public string Temp2 { get; set; }

// public string Temp3 { get; set; }
// }
//}




脚本实际上就是一个C#实现类,需要实现IDynamicSQL接口,返回新的list和新实体,该功能需一定的C#知识,以及查阅框架ORM SqlSugar 的实体定义