コード例 #1
0
ファイル: PinusDBStorage.cs プロジェクト: zlw-team/IoTSharp
        /// <summary>
        /// 转换获取到的值
        /// </summary>
        /// <param name="db"></param>
        /// <param name="sql"></param>
        /// <param name="devid"></param>
        /// <returns></returns>
        private List <TelemetryDataDto> SqlToTDD(PinusConnection db, string sql, Guid devid)
        {
            List <TelemetryDataDto> dt = new List <TelemetryDataDto>();
            var kts = db.CreateCommand(sql).ExecuteReader().ToList <(long keyid, string keyname, string datatype)>();

            kts.ForEach(kf =>
            {
                TelemetryDataDto telemetry = new TelemetryDataDto()
                {
                    KeyName = kf.keyname
                };
                try
                {
                    DataType datatype = (DataType)Convert.ToInt32(kf.datatype);
                    var queryvalue    = db.CreateCommand($"SELECT {datatype.ToFieldName()},tstamp from {GetDevTableName(devid)}   where  devid ={kf.keyid} order by tstamp desc  limit 1 ")
                                        .ExecuteReader().ToList <(object obj, DateTime dt)>();
                    telemetry.AttachValue(datatype, queryvalue.FirstOrDefault().obj);
                    telemetry.DateTime = queryvalue.FirstOrDefault().dt;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"{telemetry.KeyName}遇到{ex.Message}, sql:{sql}");
                }
                if (!string.IsNullOrEmpty(telemetry.KeyName))
                {
                    dt.Add(telemetry);
                }
            });
            return(dt);
        }
コード例 #2
0
ファイル: PinusDBStorage.cs プロジェクト: zlw-team/IoTSharp
        public Task <List <TelemetryDataDto> > GetTelemetryLatest(Guid deviceId)
        {
            PinusConnection         _pinus = _pinuspool.Get();
            string                  sql    = $"select  devid,devname,expand  from sys_dev  where tabname='telemetrydata_{deviceId:N}'";
            List <TelemetryDataDto> dt     = SqlToTDD(_pinus, sql, deviceId);

            _pinuspool.Return(_pinus);
            return(Task.FromResult(dt));
        }
コード例 #3
0
ファイル: PinusDBStorage.cs プロジェクト: zlw-team/IoTSharp
        public Task <List <TelemetryDataDto> > LoadTelemetryAsync(Guid deviceId, DateTime begin, DateTime end)
        {
            PinusConnection         _pinus = _pinuspool.Get();
            List <TelemetryDataDto> dt     = null;

            try
            {
                string sql = $"select  tbname,keyname  from telemetrydata where deviceid='{deviceId:N}'";
                dt = SQLToDTByDate(begin, end, _pinus, sql, deviceId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"LoadTelemetryAsync({deviceId}, {begin},{end}){ex.Message}");
            }
            finally
            {
                _pinuspool.Return(_pinus);
            }
            return(Task.FromResult(dt));
        }
コード例 #4
0
ファイル: PinusDBStorage.cs プロジェクト: zlw-team/IoTSharp
        public Task <List <TelemetryDataDto> > GetTelemetryLatest(Guid deviceId, string keys)
        {
            PinusConnection         _pinus = _pinuspool.Get();
            List <TelemetryDataDto> dt     = null;

            try
            {
                string sql = $"select  devid,devname,expand  from sys_dev  where tabname='telemetrydata_{deviceId:N}' and   in ('{ string.Join("','", keys.Split(';', ','))}')";
                dt = SqlToTDD(_pinus, sql, deviceId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"LoadTelemetryAsync({deviceId},{keys}){ex.Message}");
            }
            finally
            {
                _pinuspool.Return(_pinus);
            }
            _pinuspool.Return(_pinus);
            return(Task.FromResult(dt));
        }
コード例 #5
0
ファイル: PinusDBStorage.cs プロジェクト: zlw-team/IoTSharp
 private long?GetKeyId(Guid devid, string keyname, PinusConnection _pinus)
 {
     return(_pinus.CreateCommand($"select devid from sys_dev where tabname='{GetDevTableName(devid)}' and devname='{keyname}'").ExecuteScalar() as long?);
 }
コード例 #6
0
ファイル: PinusDBStorage.cs プロジェクト: zlw-team/IoTSharp
        public Task <bool> StoreTelemetryAsync(RawMsg msg)
        {
            bool            result = false;
            PinusConnection _pinus = _pinuspool.Get();

            try
            {
                string tablename = GetDevTableName(msg);
                var    _havedev  = _pinus.CreateCommand($"select count(*) from sys_table where tabname =  '{tablename}'").ExecuteScalar() as long?;
                if ((long)_havedev == 0)
                {
                    _pinus.CreateCommand($"CREATE TABLE {tablename} (devid bigint,tstamp datetime,value_type  tinyint,value_boolean bool, value_string string, value_long bigint,value_datetime datetime,value_double double)").ExecuteNonQuery();
                }

                msg.MsgBody.ToList().ForEach(kp =>
                {
                    if (kp.Value != null)
                    {
                        List <PinusParameter> parameters = new List <PinusParameter>();
                        TelemetryData tdata = new TelemetryData()
                        {
                            DateTime = DateTime.Now, DeviceId = msg.DeviceId, KeyName = kp.Key, Value_DateTime = new DateTime(1970, 1, 1)
                        };
                        tdata.FillKVToMe(kp);
                        string _type = "";
                        var cmd      = _pinus.CreateCommand();
                        switch (tdata.Type)
                        {
                        case DataType.Boolean:
                            _type = "value_boolean";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_Boolean));
                            break;

                        case DataType.String:
                            _type = "value_string";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_String));
                            break;

                        case DataType.Long:
                            _type = "value_long";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_Long));
                            break;

                        case DataType.Double:
                            _type = "value_double";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_Double));
                            break;

                        case DataType.Json:
                            _type = "value_string";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_String));
                            break;

                        case DataType.XML:
                            _type = "value_string";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_XML));
                            break;

                        case DataType.Binary:
                            _type = "value_string";
                            cmd.Parameters.Add(new PinusParameter(_type, Hex.ToHexString(tdata.Value_Binary)));
                            break;

                        case DataType.DateTime:
                            _type = "value_datetime";
                            cmd.Parameters.Add(new PinusParameter(_type, tdata.Value_DateTime));
                            break;

                        default:
                            break;
                        }
                        long?_keyid = GetKeyId(msg.DeviceId, kp.Key, _pinus);
                        if (!_keyid.HasValue)
                        {
                            long?maxid   = _pinus.CreateCommand($"select  max(devid)  from sys_dev  where tabname='{tablename}'").ExecuteScalar() as long?;
                            long currdev = maxid.GetValueOrDefault() + 1;
                            _pinus.CreateCommand($"INSERT INTO sys_dev(tabname, devname,devid,expand) VALUES('{tablename}','{kp.Key}',{currdev},'{(int)tdata.Type}')").ExecuteNonQuery();
                            _keyid = GetKeyId(msg.DeviceId, kp.Key, _pinus);
                        }
                        cmd.CommandText = $"INSERT INTO {tablename} (devid,tstamp,value_type,{_type}) VALUES({_keyid}, now(), {(int)tdata.Type}, @{_type})";
                        _logger.LogInformation(cmd.CommandText);
                        try
                        {
                            int dt = cmd.ExecuteNonQuery();
                            result = dt > 0;
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, $"{msg.DeviceId}数据处理失败{ex.Message} {ex.InnerException?.Message}");
                        }
                    }
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"{msg.DeviceId}数据处理失败{ex.Message} {ex.InnerException?.Message} ");
            }
            finally
            {
                _pinuspool.Return(_pinus);
            }
            return(Task.FromResult(result));
        }
コード例 #7
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var settings = Configuration.Get <AppSettings>();

            services.Configure((Action <AppSettings>)(setting =>
            {
                Configuration.Bind(setting);
            }));
            var healthChecksUI = services.AddHealthChecksUI(setup =>
            {
                setup.SetHeaderText("IoTSharp HealthChecks");
                //Maximum history entries by endpoint
                setup.MaximumHistoryEntriesPerEndpoint(50);
                setup.AddIoTSharpHealthCheckEndpoint();
            });

            var healthChecks = services.AddHealthChecks()
                               .AddDiskStorageHealthCheck(dso =>
            {
                System.IO.DriveInfo.GetDrives()
                .Where(d => d.DriveType != System.IO.DriveType.CDRom && d.DriveType != System.IO.DriveType.Ram)
                .Select(f => f.Name).Distinct().ToList()
                .ForEach(f => dso.AddDrive(f, 1024));
            }, name: "Disk Storage");

            switch (settings.DataBase)
            {
            case DataBaseType.MySql:
                services.ConfigureMySql(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.SqlServer:
                services.ConfigureSqlServer(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.Oracle:
                services.ConfigureOracle(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.Sqlite:
                services.ConfigureSqlite(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.PostgreSql:
            default:
                services.ConfigureNpgsql(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;
            }

            services.AddIdentity <IdentityUser, IdentityRole>()
            .AddRoles <IdentityRole>()
            .AddRoleManager <RoleManager <IdentityRole> >()
            .AddDefaultTokenProviders()
            .AddEntityFrameworkStores <ApplicationDbContext>();


            services.AddAuthentication(option =>
            {
                option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer           = true,
                    ValidateAudience         = true,
                    ValidateLifetime         = false,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer      = Configuration["JwtIssuer"],
                    ValidAudience    = Configuration["JwtAudience"],
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"]))
                };
            });


            services.AddCors();
            services.AddLogging(loggingBuilder => loggingBuilder.AddConsole());
            services.AddOpenApiDocument(configure =>
            {
                Assembly assembly     = typeof(Startup).GetTypeInfo().Assembly;
                var description       = (AssemblyDescriptionAttribute)Attribute.GetCustomAttribute(assembly, typeof(AssemblyDescriptionAttribute));
                configure.Title       = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
                configure.Version     = typeof(Startup).GetTypeInfo().Assembly.GetName().Version.ToString();
                configure.Description = description?.Description;
                configure.AddJWTSecurity();
            });

            services.AddTransient <ApplicationDBInitializer>();
            services.AddIoTSharpMqttServer(settings.MqttBroker);
            services.AddMqttClient(settings.MqttClient);
            services.AddSingleton <RetainedMessageHandler>();
            services.AddSilkierQuartz(opt =>
            {
                //opt.Add("quartz.serializer.type", "json");
                //opt.Add("quartz.jobStore.type", "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz");
                //opt.Add("quartz.jobStore.driverDelegateType", "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz");
                //opt.Add("quartz.jobStore.tablePrefix", "qrtz_");
                //opt.Add("quartz.jobStore.dataSource", "myDS");
                //opt.Add("quartz.dataSource.myDS.provider", "Npgsql");
                //opt.Add("quartz.dataSource.myDS.connectionString", Configuration.GetConnectionString("IoTSharp"));
                opt.Add("quartz.plugin.recentHistory.type", "Quartz.Plugins.RecentHistory.ExecutionHistoryPlugin, Quartz.Plugins.RecentHistory");
                opt.Add("quartz.plugin.recentHistory.storeType", "Quartz.Plugins.RecentHistory.Impl.InProcExecutionHistoryStore, Quartz.Plugins.RecentHistory");
            });
            services.AddControllers();

            services.AddMemoryCache();
            string _hc_Caching = $"{nameof(CachingUseIn)}-{Enum.GetName(settings.CachingUseIn)}";

            services.AddEasyCaching(options =>
            {
                switch (settings.CachingUseIn)
                {
                case CachingUseIn.Redis:
                    options.UseRedis(config =>
                    {
                        settings.CachingUseRedisHosts?.Split(';').ToList().ForEach(h =>
                        {
                            var hx = h.Split(':');
                            config.DBConfig.Endpoints.Add(new ServerEndPoint(hx[0], int.Parse(hx[1])));
                        });
                    }, "iotsharp");
                    healthChecks.AddRedis(settings.CachingUseRedisHosts, name: _hc_Caching);
                    break;

                case CachingUseIn.LiteDB:
                    options.UseLiteDB(cfg => cfg.DBConfig = new EasyCaching.LiteDB.LiteDBDBOptions()
                    {
                    }, name: "iotsharp");
                    break;

                case CachingUseIn.InMemory:
                default:
                    options.UseInMemory("iotsharp");
                    break;
                }
            });
            string _hc_telemetryStorage = $"{nameof(TelemetryStorage)}-{Enum.GetName(settings.TelemetryStorage)}";

            switch (settings.TelemetryStorage)
            {
            case TelemetryStorage.Sharding:
                services.AddEFCoreSharding(config =>
                {
                    switch (settings.DataBase)
                    {
                    case DataBaseType.MySql:
                        config.UseMySqlToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.SqlServer:
                        config.UseSqlServerToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.Oracle:
                        config.UseOracleToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.Sqlite:
                        config.UseSQLiteToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.PostgreSql:
                    default:
                        config.UseNpgsqlToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;
                    }
                    config.SetEntityAssemblies(new Assembly[] { typeof(TelemetryData).Assembly });
                });
                services.AddSingleton <IStorage, ShardingStorage>();
                break;

            case TelemetryStorage.Taos:
                services.AddSingleton <IStorage, TaosStorage>();
                services.AddObjectPool(() => new TaosConnection(settings.ConnectionStrings["TelemetryStorage"]));
                healthChecks.AddTDengine(Configuration.GetConnectionString("TelemetryStorage"), name: _hc_telemetryStorage);
                break;

            case TelemetryStorage.InfluxDB:
                //https://github.com/julian-fh/influxdb-setup
                services.AddSingleton <IStorage, InfluxDBStorage>();
                //"TelemetryStorage": "http://localhost:8086/?org=iotsharp&bucket=iotsharp-bucket&token=iotsharp-token"
                services.AddObjectPool(() => InfluxDBClientFactory.Create(Configuration.GetConnectionString("TelemetryStorage")));
                //healthChecks.AddInfluxDB(Configuration.GetConnectionString("TelemetryStorage"),name: _hc_telemetryStorage);
                break;

            case TelemetryStorage.PinusDB:
                services.AddSingleton <IStorage, PinusDBStorage>();
                services.AddObjectPool(() =>
                {
                    var cnt = new PinusConnection(settings.ConnectionStrings["TelemetryStorage"]);
                    cnt.Open();
                    return(cnt);
                });
                healthChecks.AddPinusDB(Configuration.GetConnectionString("TelemetryStorage"), name: _hc_telemetryStorage);
                break;

            case TelemetryStorage.TimescaleDB:
                services.AddSingleton <IStorage, TimescaleDBStorage>();
                break;

            case TelemetryStorage.SingleTable:
            default:
                services.AddSingleton <IStorage, EFStorage>();
                break;
            }

            services.AddTransient <IEventBusHandler, EventBusHandler>();
            if (settings.ZMQOption != null)
            {
                services.AddHostedZeroMQ(cfg => cfg = settings.ZMQOption);
            }
            services.AddCap(x =>
            {
                string _hc_EventBusStore     = $"{nameof(EventBusStore)}-{Enum.GetName(settings.EventBusStore)}";
                x.SucceedMessageExpiredAfter = settings.SucceedMessageExpiredAfter;
                x.ConsumerThreadCount        = settings.ConsumerThreadCount;
                switch (settings.EventBusStore)
                {
                case EventBusStore.PostgreSql:
                    x.UsePostgreSql(Configuration.GetConnectionString("EventBusStore"));
                    healthChecks.AddNpgSql(Configuration.GetConnectionString("EventBusStore"), name: _hc_EventBusStore);
                    break;

                case EventBusStore.MongoDB:
                    x.UseMongoDB(Configuration.GetConnectionString("EventBusStore"));      //注意,仅支持MongoDB 4.0+集群
                    healthChecks.AddMongoDb(Configuration.GetConnectionString("EventBusStore"), name: _hc_EventBusStore);
                    break;

                case EventBusStore.LiteDB:
                    x.UseLiteDBStorage(Configuration.GetConnectionString("EventBusStore"));
                    break;

                case EventBusStore.InMemory:
                default:
                    x.UseInMemoryStorage();
                    break;
                }
                string _hc_EventBusMQ = $"{nameof(EventBusMQ)}-{Enum.GetName(settings.EventBusMQ)}";
                switch (settings.EventBusMQ)
                {
                case EventBusMQ.RabbitMQ:
                    var url = new Uri(Configuration.GetConnectionString("EventBusMQ"));
                    x.UseRabbitMQ(cfg =>
                    {
                        cfg.ConnectionFactoryOptions = cf =>
                        {
                            cf.AutomaticRecoveryEnabled = true;
                            cf.Uri = new Uri(Configuration.GetConnectionString("EventBusMQ"));
                        };
                    });
                    //amqp://guest:guest@localhost:5672
                    healthChecks.AddRabbitMQ(connectionFactory =>
                    {
                        var factory = new ConnectionFactory()
                        {
                            Uri = new Uri(Configuration.GetConnectionString("EventBusMQ")),
                            AutomaticRecoveryEnabled = true
                        };
                        return(factory.CreateConnection());
                    }, _hc_EventBusMQ);
                    break;

                case EventBusMQ.Kafka:
                    x.UseKafka(Configuration.GetConnectionString("EventBusMQ"));
                    healthChecks.AddKafka(cfg =>
                    {
                        cfg.BootstrapServers = Configuration.GetConnectionString("EventBusMQ");
                    }, name: _hc_EventBusMQ);
                    break;

                case EventBusMQ.ZeroMQ:
                    x.UseZeroMQ(cfg =>
                    {
                        cfg.HostName = Configuration.GetConnectionString("EventBusMQ") ?? "127.0.0.1";
                        cfg.Pattern  = MaiKeBing.CAP.NetMQPattern.PushPull;
                    });
                    break;

                case EventBusMQ.InMemory:
                default:
                    x.UseInMemoryMessageQueue();
                    break;
                }
                x.UseDashboard();
                if (settings.Discovery != null)
                {
                    x.UseDiscovery(cfg => cfg = settings.Discovery);
                }
            });
        }
コード例 #8
0
ファイル: Startup.cs プロジェクト: IoTSharp/IoTSharp
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var settings = Configuration.Get <AppSettings>();

            services.Configure((Action <AppSettings>)(setting =>
            {
                var option = setting.MqttBroker;
                Configuration.Bind(setting);
            }));
            var healthChecksUI = services.AddHealthChecksUI(setup =>
            {
                setup.SetHeaderText("IoTSharp HealthChecks");
                //Maximum history entries by endpoint
                setup.MaximumHistoryEntriesPerEndpoint(50);
                setup.AddIoTSharpHealthCheckEndpoint();
            });

            var healthChecks = services.AddHealthChecks()
                               .AddDiskStorageHealthCheck(dso =>
            {
                System.IO.DriveInfo.GetDrives()
                .Where(d => d.DriveType != System.IO.DriveType.CDRom && d.DriveType != System.IO.DriveType.Ram)
                .Select(f => f.Name).Distinct().ToList()
                .ForEach(f => dso.AddDrive(f, 1024));
            }, name: "Disk Storage");

            switch (settings.DataBase)
            {
            case DataBaseType.MySql:
                services.ConfigureMySql(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.SqlServer:
                services.ConfigureSqlServer(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.Oracle:
                services.ConfigureOracle(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.Sqlite:
                services.ConfigureSqlite(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;

            case DataBaseType.InMemory:
                services.ConfigureInMemory(settings.DbContextPoolSize, healthChecksUI);

                break;

            case DataBaseType.PostgreSql:
            default:
                services.ConfigureNpgsql(Configuration.GetConnectionString("IoTSharp"), settings.DbContextPoolSize, healthChecks, healthChecksUI);
                break;
            }

            services.AddIdentity <IdentityUser, IdentityRole>()
            .AddRoles <IdentityRole>()
            .AddRoleManager <RoleManager <IdentityRole> >()
            .AddDefaultTokenProviders()
            .AddEntityFrameworkStores <ApplicationDbContext>();



            var tokenValidationParams = new TokenValidationParameters
            {
                ValidateIssuer           = true,
                ValidateAudience         = true,
                ValidateLifetime         = true,
                RequireExpirationTime    = true,
                RequireSignedTokens      = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer      = Configuration["JwtIssuer"],
                ValidAudience    = Configuration["JwtAudience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtKey"])),
                //     ClockSkew=TimeSpan.Zero //JWT的缓冲时间默认5分钟,token实际过期时间为 appsettings.json 当中JwtExpireHours配置的时间(小时)加上这个时间。
            };

            services.AddSingleton(tokenValidationParams);

            services.AddAuthentication(option =>
            {
                option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
                option.DefaultScheme             = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.SaveToken = true;
                options.TokenValidationParameters = tokenValidationParams;
            });

            services.AddCors();
            services.AddLogging(loggingBuilder =>
            {
                loggingBuilder.AddConsole();
                loggingBuilder.AddRinLogger();
            }
                                );
            services.AddRin();
            services.AddOpenApiDocument(configure =>
            {
                Assembly assembly     = typeof(Startup).GetTypeInfo().Assembly;
                var description       = (AssemblyDescriptionAttribute)Attribute.GetCustomAttribute(assembly, typeof(AssemblyDescriptionAttribute));
                configure.Title       = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
                configure.Version     = typeof(Startup).GetTypeInfo().Assembly.GetName().Version.ToString();
                configure.Description = description?.Description;
                configure.AddJWTSecurity();
            });

            services.AddTransient <ApplicationDBInitializer>();
            services.AddIoTSharpMqttServer(settings.MqttBroker);
            services.AddMqttClient(settings.MqttClient);
            services.AddSilkierQuartz(options =>
            {
                options.VirtualPathRoot       = "/quartz";
                options.UseLocalTime          = true;
                options.DefaultDateFormat     = "yyyy-MM-dd";
                options.DefaultTimeFormat     = "HH:mm:ss";
                options.CronExpressionOptions = new CronExpressionDescriptor.Options()
                {
                    DayOfWeekStartIndexZero = false //Quartz uses 1-7 as the range
                };
            }, authenticationOptions =>
            {
                authenticationOptions.AuthScheme              = CookieAuthenticationDefaults.AuthenticationScheme;
                authenticationOptions.SilkierQuartzClaim      = "Silkier";
                authenticationOptions.SilkierQuartzClaimValue = "Quartz";
                authenticationOptions.UserName          = settings.SilkierUsername;
                authenticationOptions.UserPassword      = settings.SilkierPassword;
                authenticationOptions.AccessRequirement = SilkierQuartzAuthenticationOptions.SimpleAccessRequirement.AllowAnonymous;//登录认证有问题
            }, stdSchedulerFactoryOption =>
            {
                //opt.Add("quartz.serializer.type", "json");
                //opt.Add("quartz.jobStore.type", "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz");
                //opt.Add("quartz.jobStore.driverDelegateType", "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz");
                //opt.Add("quartz.jobStore.tablePrefix", "qrtz_");
                //opt.Add("quartz.jobStore.dataSource", "myDS");
                //opt.Add("quartz.dataSource.myDS.provider", "Npgsql");
                //opt.Add("quartz.dataSource.myDS.connectionString", Configuration.GetConnectionString("IoTSharp"));
                stdSchedulerFactoryOption.Add("quartz.plugin.recentHistory.type", "Quartz.Plugins.RecentHistory.ExecutionHistoryPlugin, Quartz.Plugins.RecentHistory");
                stdSchedulerFactoryOption.Add("quartz.plugin.recentHistory.storeType", "Quartz.Plugins.RecentHistory.Impl.InProcExecutionHistoryStore, Quartz.Plugins.RecentHistory");
            }
                                      );
            services.AddControllers();

            services.AddMemoryCache();
            string _hc_Caching = $"{nameof(CachingUseIn)}-{Enum.GetName(settings.CachingUseIn)}";

            services.AddEasyCaching(options =>
            {
                switch (settings.CachingUseIn)
                {
                case CachingUseIn.Redis:
                    options.UseRedis(config =>
                    {
                        settings.CachingUseRedisHosts?.Split(';').ToList().ForEach(h =>
                        {
                            var hx = h.Split(':');
                            config.DBConfig.Endpoints.Add(new ServerEndPoint(hx[0], int.Parse(hx[1])));
                        });
                    }, "iotsharp");
                    healthChecks.AddRedis(settings.CachingUseRedisHosts, name: _hc_Caching);
                    break;

                case CachingUseIn.LiteDB:
                    options.UseLiteDB(cfg => cfg.DBConfig = new EasyCaching.LiteDB.LiteDBDBOptions()
                    {
                    }, name: "iotsharp");
                    break;

                case CachingUseIn.InMemory:
                default:
                    options.UseInMemory("iotsharp");
                    break;
                }
            });
            string _hc_telemetryStorage = $"{nameof(TelemetryStorage)}-{Enum.GetName(settings.TelemetryStorage)}";

            switch (settings.TelemetryStorage)
            {
            case TelemetryStorage.Sharding:
                services.AddEFCoreSharding(config =>
                {
                    switch (settings.DataBase)
                    {
                    case DataBaseType.MySql:
                        config.UseMySqlToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.SqlServer:
                        config.UseSqlServerToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.Oracle:
                        config.UseOracleToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.Sqlite:
                        config.UseSQLiteToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;

                    case DataBaseType.PostgreSql:
                    default:
                        config.UseNpgsqlToSharding(Configuration.GetConnectionString("TelemetryStorage"), settings.Sharding.ExpandByDateMode);
                        break;
                    }
                    config.SetEntityAssemblies(new Assembly[] { typeof(TelemetryData).Assembly });
                });
                services.AddSingleton <IStorage, ShardingStorage>();
                break;

            case TelemetryStorage.Taos:
                services.AddSingleton <IStorage, TaosStorage>();
                services.AddObjectPool(() => new TaosConnection(settings.ConnectionStrings["TelemetryStorage"]));
                healthChecks.AddTDengine(Configuration.GetConnectionString("TelemetryStorage"), name: _hc_telemetryStorage);
                break;

            case TelemetryStorage.InfluxDB:
                //https://github.com/julian-fh/influxdb-setup
                services.AddSingleton <IStorage, InfluxDBStorage>();
                //"TelemetryStorage": "http://localhost:8086/?org=iotsharp&bucket=iotsharp-bucket&token=iotsharp-token"
                services.AddObjectPool(() => InfluxDBClientFactory.Create(Configuration.GetConnectionString("TelemetryStorage")));
                //healthChecks.AddInfluxDB(Configuration.GetConnectionString("TelemetryStorage"),name: _hc_telemetryStorage);
                break;

            case TelemetryStorage.PinusDB:
                services.AddSingleton <IStorage, PinusDBStorage>();
                services.AddObjectPool(() =>
                {
                    var cnt = new PinusConnection(settings.ConnectionStrings["TelemetryStorage"]);
                    cnt.Open();
                    return(cnt);
                });
                healthChecks.AddPinusDB(Configuration.GetConnectionString("TelemetryStorage"), name: _hc_telemetryStorage);
                break;

            case TelemetryStorage.TimescaleDB:
                services.AddSingleton <IStorage, TimescaleDBStorage>();
                break;

            case TelemetryStorage.SingleTable:
            default:
                services.AddSingleton <IStorage, EFStorage>();
                break;
            }

            services.AddTransient <IEventBusHandler, EventBusHandler>();
            if (settings.ZMQOption != null)
            {
                services.AddHostedZeroMQ(cfg => cfg = settings.ZMQOption);
            }
            services.AddCap(x =>
            {
                string _hc_EventBusStore     = $"{nameof(EventBusStore)}-{Enum.GetName(settings.EventBusStore)}";
                x.SucceedMessageExpiredAfter = settings.SucceedMessageExpiredAfter;
                x.ConsumerThreadCount        = settings.ConsumerThreadCount;
                switch (settings.EventBusStore)
                {
                case EventBusStore.PostgreSql:
                    x.UsePostgreSql(Configuration.GetConnectionString("EventBusStore"));
                    healthChecks.AddNpgSql(Configuration.GetConnectionString("EventBusStore"), name: _hc_EventBusStore);
                    break;

                case EventBusStore.MongoDB:
                    x.UseMongoDB(Configuration.GetConnectionString("EventBusStore"));      //注意,仅支持MongoDB 4.0+集群
                    healthChecks.AddMongoDb(Configuration.GetConnectionString("EventBusStore"), name: _hc_EventBusStore);
                    break;

                case EventBusStore.LiteDB:
                    x.UseLiteDBStorage(Configuration.GetConnectionString("EventBusStore"));
                    break;

                case EventBusStore.InMemory:
                default:
                    x.UseInMemoryStorage();
                    break;
                }
                string _hc_EventBusMQ = $"{nameof(EventBusMQ)}-{Enum.GetName(settings.EventBusMQ)}";
                switch (settings.EventBusMQ)
                {
                case EventBusMQ.RabbitMQ:
                    var url = new Uri(Configuration.GetConnectionString("EventBusMQ"));
                    x.UseRabbitMQ(cfg =>
                    {
                        cfg.ConnectionFactoryOptions = cf =>
                        {
                            cf.AutomaticRecoveryEnabled = true;
                            cf.Uri = new Uri(Configuration.GetConnectionString("EventBusMQ"));
                        };
                    });
                    //amqp://guest:guest@localhost:5672
                    healthChecks.AddRabbitMQ(connectionFactory =>
                    {
                        var factory = new ConnectionFactory()
                        {
                            Uri = new Uri(Configuration.GetConnectionString("EventBusMQ")),
                            AutomaticRecoveryEnabled = true
                        };
                        return(factory.CreateConnection());
                    }, _hc_EventBusMQ);
                    break;

                case EventBusMQ.Kafka:
                    x.UseKafka(Configuration.GetConnectionString("EventBusMQ"));
                    healthChecks.AddKafka(cfg =>
                    {
                        cfg.BootstrapServers = Configuration.GetConnectionString("EventBusMQ");
                    }, name: _hc_EventBusMQ);
                    break;

                case EventBusMQ.ZeroMQ:
                    x.UseZeroMQ(cfg =>
                    {
                        cfg.HostName = Configuration.GetConnectionString("EventBusMQ") ?? "127.0.0.1";
                        cfg.Pattern  = MaiKeBing.CAP.NetMQPattern.PushPull;
                    });
                    break;

                case EventBusMQ.InMemory:
                default:
                    x.UseInMemoryMessageQueue();
                    break;
                }
                x.UseDashboard();
                if (settings.Discovery != null)
                {
                    x.UseDiscovery(cfg => cfg = settings.Discovery);
                }
            });

            services.Configure <BaiduTranslateProfile>(Configuration.GetSection("BaiduTranslateProfile"));
            services.AddControllers().AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });
            services.AddRazorPages();

            // In production, the Angular files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });
            services.AddScriptEngines(Configuration.GetSection("EngineSetting"));
            services.AddTransient <FlowRuleProcessor>();
            services.AddSingleton <TaskExecutorHelper>();
            services.AddTransient <PublishAttributeDataTask>();
            services.AddTransient <PublishTelemetryDataTask>();
        }