├── .editorconfig ├── .gitignore ├── DLL ├── NewLife.Core.XML ├── NewLife.Core.dll ├── NewLife.Core.pdb ├── NewLife.Cube.XML ├── NewLife.Cube.dll ├── NewLife.Cube.pdb ├── NewLife.MQ.XML ├── NewLife.MQ.dll ├── NewLife.MQ.pdb ├── XCode.XML ├── XCode.dll ├── XCode.pdb └── 更新DLL.cs ├── LICENSE ├── Readme.MD ├── Vsd.Data ├── Entity │ ├── 产品.Biz.cs │ ├── 产品.cs │ ├── 设备.Biz.cs │ ├── 设备.cs │ ├── 设备历史.Biz.cs │ ├── 设备历史.cs │ ├── 设备在线.Biz.cs │ ├── 设备在线.cs │ ├── 设备指令.Biz.cs │ └── 设备指令.cs ├── Vsd.Data.csproj ├── Vsd.xml └── XCoder.tt ├── Vsd.Server ├── App.config ├── Program.cs ├── Setting.cs ├── Vsd.Server.csproj ├── VsdServer.cs └── link.ico ├── Vsd.Web ├── App_Start │ └── RouteConfig.cs ├── Areas │ └── Device │ │ ├── Controllers │ │ ├── DeviceCommandController.cs │ │ ├── DeviceController.cs │ │ ├── DeviceHistoryController.cs │ │ ├── DeviceOnlineController.cs │ │ └── ProductController.cs │ │ ├── Views │ │ ├── DeviceCommand │ │ │ ├── _List_Toolbar_Batch.cshtml │ │ │ └── _List_Toolbar_Batch.generated.cs │ │ ├── DeviceHistory │ │ │ ├── _List_Toolbar.cshtml │ │ │ └── _List_Toolbar.generated.cs │ │ ├── DeviceOnline │ │ │ ├── _List_Toolbar.cshtml │ │ │ └── _List_Toolbar.generated.cs │ │ └── Web.config │ │ └── VsdAreaRegistration.cs ├── Global.asax ├── Global.asax.cs ├── Properties │ ├── AssemblyInfo.cs │ └── PublishProfiles │ │ └── Front.pubxml ├── Vsd.Web.csproj ├── Web.config ├── favicon.ico └── packages.config ├── Vsd.sln ├── WiFi.Data ├── Entity │ ├── 原始数据.Biz.cs │ ├── 原始数据.cs │ ├── 设备.Biz.cs │ ├── 设备.cs │ ├── 设备历史.Biz.cs │ ├── 设备历史.cs │ ├── 设备在线.Biz.cs │ └── 设备在线.cs ├── WiFi.Data.csproj ├── WiFi.xml └── XCoder.tt ├── WiFi.Server ├── App.config ├── Program.cs ├── Setting.cs ├── WiFi.Server.csproj ├── WiFiServer.cs └── link.ico ├── WiFi.Web ├── App_Start │ └── RouteConfig.cs ├── Areas │ └── WiFi │ │ ├── Controllers │ │ ├── DeviceController.cs │ │ ├── DeviceHistoryController.cs │ │ ├── DeviceOnlineController.cs │ │ └── RawDataController.cs │ │ ├── Views │ │ ├── Device │ │ │ ├── _List_Search.cshtml │ │ │ └── _List_Search.generated.cs │ │ ├── DeviceHistory │ │ │ ├── _List_Search.cshtml │ │ │ └── _List_Search.generated.cs │ │ ├── DeviceOnline │ │ │ ├── _List_Search.cshtml │ │ │ └── _List_Search.generated.cs │ │ └── Web.config │ │ └── WiFiAreaRegistration.cs ├── Global.asax ├── Global.asax.cs ├── Properties │ ├── AssemblyInfo.cs │ └── PublishProfiles │ │ └── Front.pubxml ├── Web.config ├── WiFi.Web.csproj ├── favicon.ico └── packages.config ├── WiFi.sln ├── link.ico ├── xLink.Client ├── App.config ├── Common │ └── MachineInfo.cs ├── FrmDevice.Designer.cs ├── FrmDevice.cs ├── FrmDevice.resx ├── FrmMain.Designer.cs ├── FrmMain.cs ├── FrmMain.resx ├── FrmUser.Designer.cs ├── FrmUser.cs ├── FrmUser.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ ├── Settings.settings │ └── app.manifest ├── Services │ ├── DeviceClient.cs │ ├── LinkClient.cs │ └── UserClient.cs ├── Setting.cs ├── UIConfig.cs ├── link.ico └── xLink.Client.csproj ├── xLink.Data ├── Entity │ ├── MyModel.cs │ ├── 产品.Biz.cs │ ├── 产品.cs │ ├── 产品版本.Biz.cs │ ├── 产品版本.cs │ ├── 子设备.Biz.cs │ ├── 子设备.cs │ ├── 用户.Biz.cs │ ├── 用户.cs │ ├── 用户历史.Biz.cs │ ├── 用户历史.cs │ ├── 用户在线.Biz.cs │ ├── 用户在线.cs │ ├── 设备.Biz.cs │ ├── 设备.cs │ ├── 设备历史.Biz.cs │ ├── 设备历史.cs │ ├── 设备命令.Biz.cs │ ├── 设备命令.cs │ ├── 设备在线.Biz.cs │ ├── 设备在线.cs │ ├── 设备统计.Biz.cs │ ├── 设备统计.cs │ ├── 设备配置.Biz.cs │ └── 设备配置.cs ├── LinkClient.cs ├── LinkServer.cs ├── Services │ ├── DeviceService.cs │ ├── LinkService.cs │ └── UserService.cs ├── XCoder.tt ├── xLink.Data.csproj └── xLink.xml ├── xLink.HttpServer ├── Common │ ├── ApiFilterAttribute.cs │ ├── DateTimeConverter.cs │ ├── RequestExt.cs │ ├── TokenFilter.cs │ ├── TokenSession.cs │ ├── WebHelper.cs │ └── XLogger.cs ├── Controllers │ ├── ApiController.cs │ ├── BaseController.cs │ └── DeviceController.cs ├── Models │ └── ConfigModel.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Services │ ├── DeviceOnlineService.cs │ ├── QueueService.cs │ └── TokenService.cs ├── Setting.cs ├── Startup.cs ├── appsettings.json └── xLink.HttpServer.csproj ├── xLink.Server ├── App.config ├── Program.cs ├── Setting.cs ├── link.ico └── xLink.Server.csproj ├── xLink.Web ├── Areas │ └── Devices │ │ ├── Controllers │ │ ├── DeviceCommandController.cs │ │ ├── DeviceConfigController.cs │ │ ├── DeviceController.cs │ │ ├── DeviceHistoryController.cs │ │ ├── DeviceOnlineController.cs │ │ ├── DeviceStatController.cs │ │ ├── ProductController.cs │ │ ├── ProductVersionController.cs │ │ └── SubDeviceController.cs │ │ ├── DevicesArea.cs │ │ └── Views │ │ ├── Device │ │ ├── _List_Data.cshtml │ │ └── _List_Search.cshtml │ │ ├── DeviceCommand │ │ └── _List_Data.cshtml │ │ ├── DeviceConfig │ │ ├── _List_Data.cshtml │ │ └── _List_Search.cshtml │ │ ├── DeviceHistory │ │ ├── _List_Data.cshtml │ │ └── _List_Search.cshtml │ │ ├── DeviceOnline │ │ ├── _List_Data.cshtml │ │ ├── _List_Search.cshtml │ │ └── _List_Toolbar_Batch.cshtml │ │ ├── DeviceStat │ │ └── _List_Search.cshtml │ │ ├── Product │ │ └── _List_Data.cshtml │ │ └── _ViewImports.cshtml ├── Controllers │ └── ApiController.cs ├── Entity │ ├── Build.cs │ ├── Build.tt │ ├── Build_netcore.cs │ ├── Build_netcore.tt │ └── Model.xml ├── Program.cs ├── Properties │ └── launchSettings.json ├── Startup.cs ├── appsettings.json └── xLink.Web.csproj ├── xLink.sln └── xLink ├── Common └── MachineHelper.cs ├── Models ├── DataModel.cs ├── DeviceInfo.cs ├── IHistory.cs ├── IOnline.cs ├── LoginInfo.cs ├── PingInfo.cs ├── ServiceInfo.cs └── UpgradeInfo.cs └── xLink.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 3 | ################################################################################ 4 | 5 | [Dd]ebug/ 6 | [Dd]ebugPublic/ 7 | [Rr]elease/ 8 | [Rr]eleases/ 9 | x64/ 10 | x86/ 11 | build/ 12 | bld/ 13 | [Bb]in/ 14 | [Oo]bj/ 15 | /.vs 16 | /Log 17 | /packages 18 | /Data 19 | Content/ 20 | Config/ 21 | Plugins/ 22 | *.log 23 | *.user 24 | /Test 25 | /xLink.Master/Master数据字典.htm 26 | /xLink.Device/Device数据字典.htm 27 | set.config 28 | /Client 29 | /Server 30 | /Avatars 31 | /BinServer 32 | /BinClient 33 | /BinVsd 34 | /BinWiFi 35 | -------------------------------------------------------------------------------- /DLL/NewLife.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/NewLife.Core.dll -------------------------------------------------------------------------------- /DLL/NewLife.Core.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/NewLife.Core.pdb -------------------------------------------------------------------------------- /DLL/NewLife.Cube.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/NewLife.Cube.dll -------------------------------------------------------------------------------- /DLL/NewLife.Cube.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/NewLife.Cube.pdb -------------------------------------------------------------------------------- /DLL/NewLife.MQ.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/NewLife.MQ.dll -------------------------------------------------------------------------------- /DLL/NewLife.MQ.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/NewLife.MQ.pdb -------------------------------------------------------------------------------- /DLL/XCode.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/XCode.dll -------------------------------------------------------------------------------- /DLL/XCode.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/DLL/XCode.pdb -------------------------------------------------------------------------------- /DLL/更新DLL.cs: -------------------------------------------------------------------------------- 1 | // 自动选择最新的文件源 2 | var di = ".".AsDirectory(); 3 | var srcs = new String[] { @"..\..\Bin", @"C:\X\DLL", @"C:\X\Bin", @"D:\X\Bin", @"E:\X\DLL", @"E:\X\Bin" }; 4 | di.CopyIfNewer(srcs, "*.dll;*.exe;*.xml;*.pdb;*.cs"); 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 新生命开发团队 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Vsd.Data/Entity/产品.Biz.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Data; 2 | using NewLife.Security; 3 | using System; 4 | using System.Collections.Generic; 5 | using XCode; 6 | using XCode.Membership; 7 | 8 | namespace Vsd.Entity 9 | { 10 | /// 产品 11 | public partial class Product : Entity 12 | { 13 | #region 对象操作 14 | static Product() 15 | { 16 | // 累加字段 17 | //var df = Meta.Factory.AdditionalFields; 18 | //df.Add(__.Status); 19 | 20 | // 过滤器 UserModule、TimeModule、IPModule 21 | Meta.Modules.Add(); 22 | Meta.Modules.Add(); 23 | Meta.Modules.Add(); 24 | 25 | // 单对象缓存 26 | var sc = Meta.SingleCache; 27 | sc.FindSlaveKeyMethod = k => Find(__.Code, k); 28 | sc.GetSlaveKeyMethod = e => e.Code; 29 | } 30 | 31 | /// 验证数据,通过抛出异常的方式提示验证失败。 32 | /// 是否插入 33 | public override void Valid(Boolean isNew) 34 | { 35 | // 如果没有脏数据,则不需要进行任何处理 36 | if (!HasDirty) return; 37 | 38 | if (isNew) 39 | { 40 | // 自动生成产品证书密钥 41 | if (Code.IsNullOrEmpty()) Code = Rand.NextString(4); 42 | if (Secret.IsNullOrEmpty()) Secret = Rand.NextString(8); 43 | } 44 | } 45 | #endregion 46 | 47 | #region 扩展属性 48 | #endregion 49 | 50 | #region 扩展查询 51 | /// 根据编号查找 52 | /// 编号 53 | /// 实体对象 54 | public static Product FindByID(Int32 id) 55 | { 56 | if (id <= 0) return null; 57 | 58 | // 实体缓存 59 | if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.ID == id); 60 | 61 | // 单对象缓存 62 | return Meta.SingleCache[id]; 63 | 64 | //return Find(_.ID == id); 65 | } 66 | 67 | /// 根据名称查找 68 | /// 名称 69 | /// 实体对象 70 | public static Product FindByName(String name) 71 | { 72 | // 实体缓存 73 | if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.Name == name); 74 | 75 | return Find(_.Name == name); 76 | } 77 | 78 | /// 根据名称查找 79 | /// 名称 80 | /// 实体对象 81 | public static Product FindByCode(String code) 82 | { 83 | // 实体缓存 84 | if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.Code == code); 85 | 86 | // 单对象缓存 87 | return Meta.SingleCache.GetItemWithSlaveKey(code) as Product; 88 | 89 | //return Find(_.Code == code); 90 | } 91 | #endregion 92 | 93 | #region 高级查询 94 | /// 高级查询 95 | /// 96 | /// 97 | /// 98 | /// 99 | /// 100 | /// 101 | public static IList Search(Boolean? enable, DateTime start, DateTime end, String key, PageParameter param) 102 | { 103 | // WhereExpression重载&和|运算符,作为And和Or的替代 104 | // SearchWhereByKeys系列方法用于构建针对字符串字段的模糊搜索,第二个参数可指定要搜索的字段 105 | var exp = SearchWhereByKeys(key, null, null); 106 | 107 | if (enable != null) exp &= _.Enable == enable.Value; 108 | 109 | exp &= _.UpdateTime.Between(start, end); 110 | 111 | return FindAll(exp, param); 112 | } 113 | #endregion 114 | 115 | #region 业务操作 116 | #endregion 117 | } 118 | } -------------------------------------------------------------------------------- /Vsd.Data/Entity/设备历史.Biz.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * XCoder v6.9.6298.42194 3 | * 作者:nnhy/X3 4 | * 时间:2017-03-31 22:14:32 5 | * 版权:版权所有 (C) 新生命开发团队 2002~2017 6 | */ 7 | using NewLife.Data; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.ComponentModel; 11 | using XCode; 12 | using XCode.Cache; 13 | using XCode.Membership; 14 | 15 | namespace Vsd.Entity 16 | { 17 | /// 设备历史 18 | public partial class DeviceHistory : Entity 19 | { 20 | #region 对象操作 21 | static DeviceHistory() 22 | { 23 | Meta.Table.DataTable.InsertOnly = true; 24 | 25 | Meta.Modules.Add(); 26 | Meta.Modules.Add(); 27 | } 28 | #endregion 29 | 30 | #region 扩展属性 31 | /// 设备 32 | public Device Device => Extends.Get(nameof(Device), k => Device.FindByID(DeviceID)); 33 | 34 | /// 设备名 35 | [Map(__.DeviceID)] 36 | public String DeviceName => Device + ""; 37 | #endregion 38 | 39 | #region 扩展查询 40 | #endregion 41 | 42 | #region 高级查询 43 | /// 高级搜索 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | /// 52 | /// 53 | public static IList Search(Int32 userid, String type, String action, Int32 result, DateTime start, DateTime end, String key, PageParameter param) 54 | { 55 | var list = Search(userid, type, action, result, start, end, key, param, false); 56 | // 如果结果为0,并且有key,则使用扩展查询,对内网外网地址进行模糊查询 57 | if (list.Count == 0 && !key.IsNullOrEmpty()) list = Search(userid, type, action, result, start, end, key, param, true); 58 | 59 | return list; 60 | } 61 | 62 | private static IList Search(Int32 tokenid, String type, String action, Int32 result, DateTime start, DateTime end, String key, PageParameter param, Boolean ext) 63 | { 64 | var exp = new WhereExpression(); 65 | 66 | if (tokenid >= 0) exp &= _.DeviceID == tokenid; 67 | if (!type.IsNullOrEmpty()) exp &= _.Type == type; 68 | if (!action.IsNullOrEmpty()) exp &= _.Action == action; 69 | if (result == 0) 70 | exp &= _.Success == false; 71 | else if (result == 1) 72 | exp &= _.Success == true; 73 | 74 | exp &= _.CreateTime.Between(start, end); 75 | 76 | if (!key.IsNullOrEmpty()) 77 | { 78 | if (ext) 79 | exp &= (_.Name.Contains(key) | _.Remark.Contains(key) | _.CreateIP.Contains(key)); 80 | else 81 | exp &= _.Name.StartsWith(key); 82 | } 83 | 84 | return FindAll(exp, param); 85 | } 86 | #endregion 87 | 88 | #region 扩展操作 89 | /// 类别名实体缓存,异步,缓存10分钟 90 | static FieldCache TypeCache = new FieldCache(_.Type); 91 | 92 | /// 获取所有类别名称 93 | /// 94 | public static IDictionary FindAllTypeName() 95 | { 96 | return TypeCache.FindAllName(); 97 | } 98 | 99 | /// 类别名实体缓存,异步,缓存10分钟 100 | static FieldCache ActionCache = new FieldCache(_.Action); 101 | 102 | /// 获取所有类别名称 103 | /// 104 | public static IDictionary FindAllActionName() 105 | { 106 | return ActionCache.FindAllName(); 107 | } 108 | #endregion 109 | 110 | #region 业务 111 | #endregion 112 | } 113 | } -------------------------------------------------------------------------------- /Vsd.Data/Vsd.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net45;netstandard2.0;net40 4 | 文胜鼎物联网 5 | 物联网通信协议 6 | 东莞文胜鼎电子科技有限公司 7 | 版权所有(C) 东莞文胜鼎电子科技有限公司 2025 8 | 1.0.2019.0714 9 | 1.0.2019.0714 10 | 1.0.* 11 | false 12 | ..\BinVsd 13 | $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml 14 | pdbonly 15 | true 16 | TRACE 17 | 18 | 19 | 20 | $(DefineConstants);NETSTANDARD2_0;__CORE__ 21 | 22 | 23 | 24 | $(DefineConstants);__WIN__ 25 | 26 | 27 | 28 | $(DefineConstants);__WIN__;NET4 29 | 30 | 31 | 32 | $(DefineConstants);DEBUG 33 | full 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | True 60 | True 61 | XCoder.tt 62 | 63 | 64 | TextTemplatingFileGenerator 65 | XCoder.log 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Vsd.Data/XCoder.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" hostSpecific="true" debug="true" #> 2 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\NewLife.Core.dll" #> 3 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\XCode.dll" #> 4 | <#@ import namespace="System.Diagnostics" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="XCode.Code" #> 7 | <#@ output extension=".log" #> 8 | <# 9 | // 设置当前工作目录 10 | PathHelper.BaseDirectory = Host.ResolvePath("."); 11 | // 导入模型文件并生成实体类,模型文件、输出目录、命名空间、连接名 12 | var n = EntityBuilder.Build(); 13 | #><#=n#> -------------------------------------------------------------------------------- /Vsd.Server/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Vsd.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Agent; 3 | using NewLife.Log; 4 | using NewLife.Net; 5 | using NewLife.Threading; 6 | using System; 7 | 8 | namespace Vsd.Server 9 | { 10 | class Program 11 | { 12 | static void Main(String[] args) => new MyService().Main(); 13 | } 14 | 15 | class MyService : AgentServiceBase 16 | { 17 | /// 构造函数 18 | public MyService() 19 | { 20 | ServiceName = "VsdServer"; 21 | 22 | // 异步初始化数据 23 | ThreadPoolX.QueueUserWorkItem(() => 24 | { 25 | var set = XCode.Setting.Current; 26 | if (set.IsNew) 27 | { 28 | set.Debug = false; 29 | set.ShowSQL = false; 30 | set.SQLiteDbPath = "../Data"; 31 | #if DEBUG 32 | set.SQLiteDbPath = "../../Data"; 33 | #endif 34 | set.SaveAsync(); 35 | } 36 | }); 37 | } 38 | 39 | /// 服务器 40 | NetServer Svr; 41 | 42 | /// 启动工作 43 | protected override void StartWork(String reason) 44 | { 45 | base.StartWork(reason); 46 | 47 | var set = Setting.Current; 48 | 49 | // 实例化服务器 50 | var svr = new VsdServer 51 | { 52 | Name = "平台", 53 | Port = set.Port, 54 | }; 55 | svr.Log = XTrace.Log; 56 | svr.SessionLog = svr.Log; 57 | 58 | if (set.Debug) 59 | { 60 | svr.SocketLog = svr.Log; 61 | //svr.LogSend = true; 62 | //svr.LogReceive = true; 63 | 64 | svr.CommandLog = true; 65 | } 66 | 67 | svr.Start(); 68 | 69 | Svr = svr; 70 | } 71 | 72 | /// 停止工作 73 | protected override void StopWork(String reason) 74 | { 75 | base.StopWork(reason); 76 | 77 | Svr.TryDispose(); 78 | Svr = null; 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /Vsd.Server/Setting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using NewLife.Xml; 4 | 5 | namespace Vsd.Server 6 | { 7 | /// 配置 8 | [XmlConfigFile("Config/Server.config", 15000)] 9 | public class Setting : XmlConfig 10 | { 11 | #region 属性 12 | /// 调试开关。默认true 13 | [Description("调试开关。默认true")] 14 | public Boolean Debug { get; set; } = true; 15 | 16 | /// 端口。默认2234 17 | [Description("端口。默认2234")] 18 | public Int32 Port { get; set; } = 2234; 19 | 20 | /// 网络日志开关。默认false 21 | [Description("网络日志开关。默认false")] 22 | public Boolean SocketDebug { get; set; } 23 | 24 | /// 编码日志开关。默认false 25 | [Description("编码日志开关。默认false")] 26 | public Boolean EncoderDebug { get; set; } 27 | #endregion 28 | 29 | #region 构造 30 | /// 实例化 31 | public Setting() 32 | { 33 | #if DEBUG 34 | EncoderDebug = true; 35 | #endif 36 | } 37 | #endregion 38 | } 39 | } -------------------------------------------------------------------------------- /Vsd.Server/Vsd.Server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net45;netcoreapp2.1;net40 6 | 文胜鼎物联网服务端 7 | 物联网云平台,负责在硬件设备以及用户端之间交互数据指令 8 | 东莞文胜鼎电子科技有限公司 9 | 版权所有(C) 东莞文胜鼎电子科技有限公司 2025 10 | 1.0.2019.0714 11 | 1.0.2019.0714 12 | 1.0.* 13 | false 14 | link.ico 15 | ..\BinVsd 16 | pdbonly 17 | true 18 | TRACE 19 | 20 | 21 | 22 | $(DefineConstants);NETSTANDARD2_0;__CORE__ 23 | 24 | 25 | 26 | $(DefineConstants);__WIN__ 27 | 28 | 29 | 30 | $(DefineConstants);__WIN__;NET4 31 | 32 | 33 | 34 | $(DefineConstants);DEBUG 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 8.2.2019.706 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /Vsd.Server/link.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/Vsd.Server/link.ico -------------------------------------------------------------------------------- /Vsd.Web/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace Vsd.Web 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "CubeHome", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Controllers/DeviceCommandController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Web.Mvc; 7 | using Vsd.Entity; 8 | using XCode.Membership; 9 | 10 | namespace Vsd.Device.Web.Controllers 11 | { 12 | [Description("设备命令")] 13 | public class DeviceCommandController : EntityController 14 | { 15 | static DeviceCommandController() 16 | { 17 | MenuOrder = 82; 18 | } 19 | 20 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 21 | /// 22 | /// 23 | protected override IEnumerable Search(Pager p) 24 | { 25 | Boolean? flag = null; 26 | if (!p["finished"].IsNullOrEmpty()) flag = p["finished"].ToBoolean(); 27 | 28 | return DeviceCommand.Search(p["deviceid"].ToInt(), p["cmd"], flag, p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 29 | } 30 | 31 | /// 启用禁用任务 32 | /// 33 | /// 34 | /// 35 | [EntityAuthorize(PermissionFlags.Update)] 36 | public ActionResult Set(Int32 id = 0, Boolean enable = true) 37 | { 38 | if (id > 0) 39 | { 40 | var dt = DeviceCommand.FindByID(id); 41 | if (dt == null) throw new ArgumentNullException(nameof(id), "找不到命令 " + id); 42 | 43 | dt.Status = enable ? CommandStatus.就绪 : CommandStatus.取消; 44 | dt.Save(); 45 | } 46 | else 47 | { 48 | var ids = Request["keys"].SplitAsInt(","); 49 | 50 | foreach (var item in ids) 51 | { 52 | var dt = DeviceCommand.FindByID(item); 53 | if (dt != null) 54 | { 55 | dt.Status = enable ? CommandStatus.就绪 : CommandStatus.取消; 56 | dt.Save(); 57 | } 58 | } 59 | } 60 | return JsonRefresh("操作成功!"); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Controllers/DeviceController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using DeviceX = Vsd.Entity.Device; 6 | 7 | namespace Vsd.Device.Web.Controllers 8 | { 9 | public class DeviceController : EntityController 10 | { 11 | static DeviceController() 12 | { 13 | MenuOrder = 90; 14 | 15 | var list = ListFields; 16 | list.RemoveField("Secret"); 17 | list.RemoveField("Data"); 18 | list.RemoveField("CreateUserID", "CreateIP", "UpdateUserID"); 19 | } 20 | 21 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 22 | /// 23 | /// 24 | protected override IEnumerable Search(Pager p) 25 | { 26 | Boolean? flag = null; 27 | if (!p["enable"].IsNullOrEmpty()) flag = p["enable"].ToBoolean(); 28 | 29 | return DeviceX.Search(p["type"], flag, p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Controllers/DeviceHistoryController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using Vsd.Entity; 7 | 8 | namespace Vsd.Device.Web.Controllers 9 | { 10 | [Description("设备操作历史")] 11 | public class DeviceHistoryController : ReadOnlyEntityController 12 | { 13 | static DeviceHistoryController() 14 | { 15 | MenuOrder = 84; 16 | 17 | var list = ListFields; 18 | list.RemoveField("CreateDeviceID"); 19 | list.AddField("Success", "Remark"); 20 | } 21 | 22 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 23 | /// 24 | /// 25 | protected override IEnumerable Search(Pager p) 26 | { 27 | return DeviceHistory.Search(p["TokenID"].ToInt(-1), p["type"], p["action"], p["result"].ToInt(-1), p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Controllers/DeviceOnlineController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using Vsd.Entity; 6 | 7 | namespace Vsd.Device.Web.Controllers 8 | { 9 | public class DeviceOnlineController : ReadOnlyEntityController 10 | { 11 | static DeviceOnlineController() 12 | { 13 | MenuOrder = 88; 14 | 15 | ListFields.RemoveField("LastError"); 16 | } 17 | 18 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 19 | /// 20 | /// 21 | protected override IEnumerable Search(Pager p) 22 | { 23 | return DeviceOnline.Search(p["Type"], p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Controllers/ProductController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using Vsd.Entity; 6 | 7 | namespace Vsd.Device.Web.Controllers 8 | { 9 | public class ProductController : EntityController 10 | { 11 | static ProductController() 12 | { 13 | MenuOrder = 100; 14 | 15 | var list = ListFields; 16 | list.RemoveField("Secret"); 17 | } 18 | 19 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 20 | /// 21 | /// 22 | protected override IEnumerable Search(Pager p) 23 | { 24 | var start = p["dtStart"].ToDateTime(); 25 | var end = p["dtEnd"].ToDateTime(); 26 | Boolean? flag = null; 27 | if (!p["enable"].IsNullOrEmpty()) flag = p["enable"].ToBoolean(); 28 | 29 | return Product.Search(flag, start, end, p["Q"], p); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Views/DeviceCommand/_List_Toolbar_Batch.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife.Common; 2 | @using System.Collections.Generic; 3 | @{ 4 | var user = ViewBag.User as IUser ?? User.Identity as IUser; 5 | var fact = ViewBag.Factory as IEntityOperate; 6 | var enableSelect = this.EnableSelect(); 7 | 8 | } 9 | @if (enableSelect) 10 | { 11 | 14 | 17 | } -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Views/DeviceHistory/_List_Toolbar.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using XCode; 4 | @using Vsd.Entity; 5 | @{ 6 | var fact = ViewBag.Factory as IEntityOperate; 7 | var page = ViewBag.Page as Pager; 8 | 9 | var dic = new Dictionary(); 10 | dic.Add(1, "成功"); 11 | dic.Add(0, "失败"); 12 | } 13 |
14 |
15 |
16 |
17 |
18 | 19 | @Html.ForDropDownList("type", DeviceHistory.FindAllTypeName(), Request["type"], "全部", true) 20 |
21 |
22 | 23 | @Html.ForDropDownList("action", DeviceHistory.FindAllActionName(), Request["action"], "全部", true) 24 |
25 |
26 | 27 | @Html.ForDropDownList("result", dic, Request["result"], "全部", true) 28 |
29 |
30 | 31 |
32 | 33 | 34 |
35 |
36 |
37 | 38 |
39 | 40 | 41 |
42 |
43 |
44 | 45 | @Html.Partial("_List_Toolbar_Search") 46 | @Html.Partial("_List_Toolbar_Adv") 47 |
48 |
49 |
50 |
51 |
52 | -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Views/DeviceOnline/_List_Toolbar.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using XCode; 4 | @using Vsd.Entity; 5 | @{ 6 | var fact = ViewBag.Factory as IEntityOperate; 7 | var page = ViewBag.Page as Pager; 8 | } 9 |
10 |
11 |
12 |
13 |
14 | 15 | @Html.ForDropDownList("Type", DeviceOnline.FindAllTypeName(), Request["Type"], "全部", true) 16 |
17 |
18 | 19 |
20 | 21 | 22 |
23 |
24 |
25 | 26 |
27 | 28 | 29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 |
43 |
44 | @Html.Partial("_List_Toolbar_Adv") 45 |
46 |
47 |
48 |
49 |
50 | -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 46 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Vsd.Web/Areas/Device/VsdAreaRegistration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Web.Mvc; 3 | using NewLife.Cube; 4 | 5 | namespace Vsd.Device.Web 6 | { 7 | [DisplayName("设备管理")] 8 | public class DeviceAreaRegistration : AreaRegistrationBase 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /Vsd.Web/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Vsd.Web.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Vsd.Web/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Mvc; 2 | using System.Web.Routing; 3 | 4 | namespace Vsd.Web 5 | { 6 | // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明, 7 | // 请访问 http://go.microsoft.com/?LinkId=9394801 8 | public class MvcApplication : System.Web.HttpApplication 9 | { 10 | protected void Application_Start() 11 | { 12 | AreaRegistration.RegisterAllAreas(); 13 | 14 | RouteConfig.RegisterRoutes(RouteTable.Routes); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Vsd.Web/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过下列特性集 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("文胜鼎物联网平台")] 9 | [assembly: AssemblyDescription("物联网平台")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyProduct("Vsd.Web")] 12 | [assembly: AssemblyCompany("东莞文胜鼎电子科技有限公司")] 13 | [assembly: AssemblyCopyright("Copyright © 东莞文胜鼎电子科技有限公司 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的某个类型, 19 | // 请针对该类型将 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("5185f285-2543-4ea7-b27e-2a14811c730e")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 内部版本号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyFileVersion("1.0.2019.0714")] 36 | 37 | /* 38 | * v1.0.2019.0714 轻量版物联网平台 39 | */ 40 | -------------------------------------------------------------------------------- /Vsd.Web/Properties/PublishProfiles/Front.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | FileSystem 9 | Release 10 | Any CPU 11 | 12 | True 13 | True 14 | True 15 | False 16 | MergeAllOutputsToASingleAssembly 17 | True 18 | Front 19 | True 20 | True 21 | ..\..\Front\Web 22 | True 23 | 24 | -------------------------------------------------------------------------------- /Vsd.Web/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Vsd.Web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/Vsd.Web/favicon.ico -------------------------------------------------------------------------------- /Vsd.Web/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Vsd.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Other", "Other", "{E9E982D4-367F-4305-ABDF-3B590673DADD}" 7 | ProjectSection(SolutionItems) = preProject 8 | Readme.MD = Readme.MD 9 | EndProjectSection 10 | EndProject 11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vsd.Data", "Vsd.Data\Vsd.Data.csproj", "{4A907003-F3A1-44DF-A6CD-D71A96AB4A6E}" 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vsd.Server", "Vsd.Server\Vsd.Server.csproj", "{7459616B-D3CE-4C69-A112-690B38CFB0EC}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vsd.Web", "Vsd.Web\Vsd.Web.csproj", "{779BC3B7-BA72-4049-837D-3DDC53FBC0A9}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {4A907003-F3A1-44DF-A6CD-D71A96AB4A6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {4A907003-F3A1-44DF-A6CD-D71A96AB4A6E}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {4A907003-F3A1-44DF-A6CD-D71A96AB4A6E}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {4A907003-F3A1-44DF-A6CD-D71A96AB4A6E}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {7459616B-D3CE-4C69-A112-690B38CFB0EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {7459616B-D3CE-4C69-A112-690B38CFB0EC}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {7459616B-D3CE-4C69-A112-690B38CFB0EC}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {7459616B-D3CE-4C69-A112-690B38CFB0EC}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Release|Any CPU.Build.0 = Release|Any CPU 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | GlobalSection(ExtensibilityGlobals) = postSolution 40 | SolutionGuid = {E2BACAC2-15CC-4C71-9436-1616D7607684} 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /WiFi.Data/Entity/设备历史.Biz.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * XCoder v6.9.6298.42194 3 | * 作者:nnhy/X3 4 | * 时间:2017-03-31 22:14:32 5 | * 版权:版权所有 (C) 新生命开发团队 2002~2017 6 | */ 7 | using NewLife.Data; 8 | using System; 9 | using System.Collections.Generic; 10 | using XCode; 11 | using XCode.Cache; 12 | using XCode.Membership; 13 | 14 | namespace WiFi.Entity 15 | { 16 | /// 设备历史 17 | public partial class DeviceHistory : Entity 18 | { 19 | #region 对象操作 20 | static DeviceHistory() 21 | { 22 | Meta.Table.DataTable.InsertOnly = true; 23 | 24 | Meta.Modules.Add(); 25 | Meta.Modules.Add(); 26 | } 27 | #endregion 28 | 29 | #region 扩展属性 30 | /// 设备 31 | public Device Device => Extends.Get(nameof(Device), k => Device.FindByID(DeviceID)); 32 | 33 | /// 设备名 34 | [Map(__.DeviceID)] 35 | public String DeviceName => Device + ""; 36 | #endregion 37 | 38 | #region 扩展查询 39 | #endregion 40 | 41 | #region 高级查询 42 | /// 高级搜索 43 | /// 44 | /// 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | public static IList Search(Int32 deviceid, String action, Boolean? success, DateTime start, DateTime end, String key, PageParameter page) 52 | { 53 | var list = Search(deviceid, action, success, start, end, key, page, false); 54 | // 如果结果为0,并且有key,则使用扩展查询,对内网外网地址进行模糊查询 55 | if (list.Count == 0 && !key.IsNullOrEmpty()) list = Search(deviceid, action, success, start, end, key, page, true); 56 | 57 | return list; 58 | } 59 | 60 | private static IList Search(Int32 deviceid, String action, Boolean? success, DateTime start, DateTime end, String key, PageParameter page, Boolean ext) 61 | { 62 | var exp = new WhereExpression(); 63 | 64 | if (deviceid >= 0) exp &= _.DeviceID == deviceid; 65 | if (!action.IsNullOrEmpty()) exp &= _.Action == action; 66 | if (success != null) exp &= _.Success == success; 67 | 68 | exp &= _.CreateTime.Between(start, end); 69 | 70 | if (!key.IsNullOrEmpty()) 71 | { 72 | if (ext) 73 | exp &= (_.Name.Contains(key) | _.Remark.Contains(key) | _.CreateIP.Contains(key)); 74 | else 75 | exp &= _.Name.StartsWith(key); 76 | } 77 | 78 | return FindAll(exp, page); 79 | } 80 | #endregion 81 | 82 | #region 扩展操作 83 | /// 类别名实体缓存,异步,缓存10分钟 84 | static FieldCache ActionCache = new FieldCache(_.Action); 85 | 86 | /// 获取所有类别名称 87 | /// 88 | public static IDictionary FindAllActionName() => ActionCache.FindAllName(); 89 | #endregion 90 | 91 | #region 业务 92 | #endregion 93 | } 94 | } -------------------------------------------------------------------------------- /WiFi.Data/WiFi.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net45;netstandard2.0;net40 4 | WiFi客流服务端 5 | 采集并存储用户WiFi数据 6 | 新生命开发团队 7 | 版权所有(C) 新生命开发团队 2025 8 | 1.0.2019.0811 9 | 1.0.2019.0811 10 | 1.0.* 11 | false 12 | pdbonly 13 | true 14 | TRACE 15 | 16 | 17 | 18 | $(DefineConstants);NETSTANDARD2_0;__CORE__ 19 | 20 | 21 | 22 | $(DefineConstants);__WIN__ 23 | 24 | 25 | 26 | $(DefineConstants);__WIN__;NET4 27 | 28 | 29 | 30 | $(DefineConstants);DEBUG 31 | full 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | True 43 | True 44 | XCoder.tt 45 | 46 | 47 | TextTemplatingFileGenerator 48 | XCoder.log 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /WiFi.Data/XCoder.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" hostSpecific="true" debug="true" #> 2 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\NewLife.Core.dll" #> 3 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\XCode.dll" #> 4 | <#@ import namespace="System.Diagnostics" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="XCode.Code" #> 7 | <#@ output extension=".log" #> 8 | <# 9 | // 设置当前工作目录 10 | PathHelper.BaseDirectory = Host.ResolvePath("."); 11 | // 导入模型文件并生成实体类,模型文件、输出目录、命名空间、连接名 12 | var n = EntityBuilder.Build(); 13 | #><#=n#> -------------------------------------------------------------------------------- /WiFi.Server/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /WiFi.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Agent; 3 | using NewLife.Log; 4 | using NewLife.Net; 5 | using NewLife.Threading; 6 | using System; 7 | 8 | namespace WiFi.Server 9 | { 10 | class Program 11 | { 12 | static void Main(String[] args) => new MyService().Main(); 13 | } 14 | 15 | class MyService : AgentServiceBase 16 | { 17 | /// 构造函数 18 | public MyService() 19 | { 20 | ServiceName = "WiFiServer"; 21 | 22 | // 异步初始化数据 23 | ThreadPoolX.QueueUserWorkItem(() => 24 | { 25 | var set = XCode.Setting.Current; 26 | if (set.IsNew) 27 | { 28 | set.Debug = false; 29 | set.ShowSQL = false; 30 | set.SQLiteDbPath = "../Data"; 31 | #if DEBUG 32 | set.SQLiteDbPath = "../../Data"; 33 | #endif 34 | set.SaveAsync(); 35 | } 36 | }); 37 | 38 | AddMenu('t', "数据测试", Test); 39 | } 40 | 41 | /// 服务器 42 | NetServer Svr; 43 | 44 | /// 启动工作 45 | protected override void StartWork(String reason) 46 | { 47 | base.StartWork(reason); 48 | 49 | var set = Setting.Current; 50 | 51 | // 实例化服务器 52 | var svr = new WiFiServer 53 | { 54 | Name = "平台", 55 | Port = set.Port, 56 | }; 57 | svr.Log = XTrace.Log; 58 | svr.SessionLog = svr.Log; 59 | 60 | if (set.Debug) 61 | { 62 | svr.SocketLog = svr.Log; 63 | //svr.LogSend = true; 64 | //svr.LogReceive = true; 65 | 66 | svr.CommandLog = true; 67 | } 68 | 69 | svr.Start(); 70 | 71 | Svr = svr; 72 | } 73 | 74 | /// 停止工作 75 | protected override void StopWork(String reason) 76 | { 77 | base.StopWork(reason); 78 | 79 | Svr.TryDispose(); 80 | Svr = null; 81 | } 82 | 83 | private void Test() 84 | { 85 | for (int i = 0; i < 100; i++) 86 | { 87 | //var rssi = -95; 88 | var rssi = -i; 89 | var d = WiFiSession.GetDistance(rssi); 90 | Console.WriteLine("{0},{1:n2}", rssi, d); 91 | } 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /WiFi.Server/Setting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using NewLife.Xml; 4 | 5 | namespace WiFi.Server 6 | { 7 | /// 配置 8 | [XmlConfigFile("Config/Server.config", 15000)] 9 | public class Setting : XmlConfig 10 | { 11 | #region 属性 12 | /// 调试开关。默认true 13 | [Description("调试开关。默认true")] 14 | public Boolean Debug { get; set; } = true; 15 | 16 | /// 端口。默认6000 17 | [Description("端口。默认6000")] 18 | public Int32 Port { get; set; } = 6000; 19 | 20 | /// 网络日志开关。默认false 21 | [Description("网络日志开关。默认false")] 22 | public Boolean SocketDebug { get; set; } 23 | 24 | /// 编码日志开关。默认false 25 | [Description("编码日志开关。默认false")] 26 | public Boolean EncoderDebug { get; set; } 27 | #endregion 28 | 29 | #region 构造 30 | /// 实例化 31 | public Setting() 32 | { 33 | #if DEBUG 34 | EncoderDebug = true; 35 | #endif 36 | } 37 | #endregion 38 | } 39 | } -------------------------------------------------------------------------------- /WiFi.Server/WiFi.Server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net45;netcoreapp2.1;net40 6 | WiFi客流服务端 7 | 采集并存储用户WiFi数据 8 | 新生命开发团队 9 | 版权所有(C) 新生命开发团队 2025 10 | 1.0.2019.0811 11 | 1.0.2019.0811 12 | 1.0.* 13 | false 14 | link.ico 15 | ..\BinWiFi 16 | pdbonly 17 | true 18 | TRACE 19 | 20 | 21 | 22 | $(DefineConstants);NETSTANDARD2_0;__CORE__ 23 | 24 | 25 | 26 | $(DefineConstants);__WIN__ 27 | 28 | 29 | 30 | $(DefineConstants);__WIN__;NET4 31 | 32 | 33 | 34 | $(DefineConstants);DEBUG 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 8.2.2019.706 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /WiFi.Server/link.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/WiFi.Server/link.ico -------------------------------------------------------------------------------- /WiFi.Web/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace WiFi.Web 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapRoute( 17 | name: "Default", 18 | url: "{controller}/{action}/{id}", 19 | defaults: new { controller = "CubeHome", action = "Index", id = UrlParameter.Optional } 20 | ); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Controllers/DeviceController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using WiFi.Entity; 6 | using DeviceX = WiFi.Entity.Device; 7 | 8 | namespace WiFi.Device.Web.Controllers 9 | { 10 | public class DeviceController : EntityController 11 | { 12 | static DeviceController() 13 | { 14 | MenuOrder = 90; 15 | 16 | var list = ListFields; 17 | list.RemoveField("Secret"); 18 | list.RemoveField("Data"); 19 | list.RemoveField("CreateUserID", "CreateIP", "UpdateUserID"); 20 | } 21 | 22 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 23 | /// 24 | /// 25 | protected override IEnumerable Search(Pager p) 26 | { 27 | var kind = (DeviceKinds)p["kind"].ToInt(); 28 | var enable = p["enable"]?.ToBoolean(); 29 | 30 | return DeviceX.Search(kind, enable, p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Controllers/DeviceHistoryController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using WiFi.Entity; 7 | 8 | namespace WiFi.Device.Web.Controllers 9 | { 10 | [Description("设备操作历史")] 11 | public class DeviceHistoryController : ReadOnlyEntityController 12 | { 13 | static DeviceHistoryController() 14 | { 15 | MenuOrder = 84; 16 | 17 | var list = ListFields; 18 | list.RemoveField("CreateDeviceID"); 19 | list.AddField("Success", "Remark"); 20 | } 21 | 22 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 23 | /// 24 | /// 25 | protected override IEnumerable Search(Pager p) 26 | { 27 | var deviceid = p["DeviceID"].ToInt(-1); 28 | var action = p["action"]; 29 | var success = p["success"]?.ToBoolean(); 30 | 31 | return DeviceHistory.Search(deviceid, action, success, p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Controllers/DeviceOnlineController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using WiFi.Entity; 6 | 7 | namespace WiFi.Device.Web.Controllers 8 | { 9 | public class DeviceOnlineController : ReadOnlyEntityController 10 | { 11 | static DeviceOnlineController() 12 | { 13 | MenuOrder = 88; 14 | 15 | ListFields.RemoveField("SessionID"); 16 | ListFields.RemoveField("LastError"); 17 | } 18 | 19 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 20 | /// 21 | /// 22 | protected override IEnumerable Search(Pager p) 23 | { 24 | var kind = (DeviceKinds)p["kind"].ToInt(); 25 | 26 | return DeviceOnline.Search(kind, p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Controllers/RawDataController.cs: -------------------------------------------------------------------------------- 1 | using NewLife.Cube; 2 | using NewLife.Web; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using WiFi.Entity; 7 | 8 | namespace WiFi.Device.Web.Controllers 9 | { 10 | [Description("原始数据")] 11 | public class RawDataController : EntityController 12 | { 13 | static RawDataController() 14 | { 15 | MenuOrder = 82; 16 | } 17 | 18 | /// 列表页视图。子控制器可重载,以传递更多信息给视图,比如修改要显示的列 19 | /// 20 | /// 21 | protected override IEnumerable Search(Pager p) 22 | { 23 | var deviceid = p["DeviceID"].ToInt(-1); 24 | 25 | return RawData.Search(deviceid, p["dtStart"].ToDateTime(), p["dtEnd"].ToDateTime(), p["Q"], p); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/Device/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using NewLife.Cube; 4 | @using XCode; 5 | @using WiFi.Entity; 6 | @{ 7 | var fact = ViewBag.Factory as IEntityOperate; 8 | var page = ViewBag.Page as Pager; 9 | } 10 |
11 | 12 | @Html.ForDropDownList("Kind", System.EnumHelper.GetDescriptions(typeof(DeviceKinds)), page["Kind"], "全部", true) 13 |
14 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/Device/_List_Search.generated.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 1591 2 | //------------------------------------------------------------------------------ 3 | // 4 | // 此代码由工具生成。 5 | // 运行时版本:4.0.30319.42000 6 | // 7 | // 对此文件的更改可能会导致不正确的行为,并且如果 8 | // 重新生成代码,这些更改将会丢失。 9 | // 10 | //------------------------------------------------------------------------------ 11 | 12 | namespace ASP 13 | { 14 | using System; 15 | using System.Collections.Generic; 16 | using System.IO; 17 | using System.Linq; 18 | using System.Net; 19 | using System.Text; 20 | using System.Web; 21 | using System.Web.Helpers; 22 | using System.Web.Mvc; 23 | using System.Web.Mvc.Ajax; 24 | using System.Web.Mvc.Html; 25 | using System.Web.Routing; 26 | using System.Web.Security; 27 | using System.Web.UI; 28 | using System.Web.WebPages; 29 | 30 | #line 1 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 31 | using NewLife; 32 | 33 | #line default 34 | #line hidden 35 | 36 | #line 3 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 37 | using NewLife.Cube; 38 | 39 | #line default 40 | #line hidden 41 | using NewLife.Reflection; 42 | 43 | #line 2 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 44 | using NewLife.Web; 45 | 46 | #line default 47 | #line hidden 48 | 49 | #line 5 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 50 | using WiFi.Entity; 51 | 52 | #line default 53 | #line hidden 54 | 55 | #line 4 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 56 | using XCode; 57 | 58 | #line default 59 | #line hidden 60 | using XCode.Membership; 61 | 62 | [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] 63 | [System.Web.WebPages.PageVirtualPathAttribute("~/Areas/WiFi/Views/Device/_List_Search.cshtml")] 64 | public partial class _Areas_WiFi_Views_Device__List_Search_cshtml : System.Web.Mvc.WebViewPage 65 | { 66 | public _Areas_WiFi_Views_Device__List_Search_cshtml() 67 | { 68 | } 69 | public override void Execute() 70 | { 71 | 72 | #line 6 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 73 | 74 | var fact = ViewBag.Factory as IEntityOperate; 75 | var page = ViewBag.Page as Pager; 76 | 77 | 78 | #line default 79 | #line hidden 80 | WriteLiteral("\r\n\r\n 类型:\r\n"); 91 | 92 | WriteLiteral(" "); 93 | 94 | 95 | #line 12 "..\..\Areas\WiFi\Views\Device\_List_Search.cshtml" 96 | Write(Html.ForDropDownList("Kind", System.EnumHelper.GetDescriptions(typeof(DeviceKinds)), page["Kind"], "全部", true)); 97 | 98 | 99 | #line default 100 | #line hidden 101 | WriteLiteral("\r\n\r\n"); 102 | 103 | } 104 | } 105 | } 106 | #pragma warning restore 1591 107 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/DeviceHistory/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using NewLife.Cube; 4 | @using XCode; 5 | @using WiFi.Entity; 6 | @{ 7 | var fact = ViewBag.Factory as IEntityOperate; 8 | var page = ViewBag.Page as Pager; 9 | 10 | var dic = new Dictionary(); 11 | dic.Add(1, "成功"); 12 | dic.Add(0, "失败"); 13 | } 14 |
15 | 16 | @Html.ForDropDownList("action", DeviceHistory.FindAllActionName(), Request["action"], "全部", true) 17 |
18 |
19 | 20 | @Html.ForDropDownList("success", dic, Request["success"], "全部", true) 21 |
22 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/DeviceHistory/_List_Search.generated.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 1591 2 | //------------------------------------------------------------------------------ 3 | // 4 | // 此代码由工具生成。 5 | // 运行时版本:4.0.30319.42000 6 | // 7 | // 对此文件的更改可能会导致不正确的行为,并且如果 8 | // 重新生成代码,这些更改将会丢失。 9 | // 10 | //------------------------------------------------------------------------------ 11 | 12 | namespace ASP 13 | { 14 | using System; 15 | using System.Collections.Generic; 16 | using System.IO; 17 | using System.Linq; 18 | using System.Net; 19 | using System.Text; 20 | using System.Web; 21 | using System.Web.Helpers; 22 | using System.Web.Mvc; 23 | using System.Web.Mvc.Ajax; 24 | using System.Web.Mvc.Html; 25 | using System.Web.Routing; 26 | using System.Web.Security; 27 | using System.Web.UI; 28 | using System.Web.WebPages; 29 | 30 | #line 1 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 31 | using NewLife; 32 | 33 | #line default 34 | #line hidden 35 | 36 | #line 3 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 37 | using NewLife.Cube; 38 | 39 | #line default 40 | #line hidden 41 | using NewLife.Reflection; 42 | 43 | #line 2 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 44 | using NewLife.Web; 45 | 46 | #line default 47 | #line hidden 48 | 49 | #line 5 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 50 | using WiFi.Entity; 51 | 52 | #line default 53 | #line hidden 54 | 55 | #line 4 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 56 | using XCode; 57 | 58 | #line default 59 | #line hidden 60 | using XCode.Membership; 61 | 62 | [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] 63 | [System.Web.WebPages.PageVirtualPathAttribute("~/Areas/WiFi/Views/DeviceHistory/_List_Search.cshtml")] 64 | public partial class _Areas_WiFi_Views_DeviceHistory__List_Search_cshtml : System.Web.Mvc.WebViewPage 65 | { 66 | public _Areas_WiFi_Views_DeviceHistory__List_Search_cshtml() 67 | { 68 | } 69 | public override void Execute() 70 | { 71 | 72 | #line 6 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 73 | 74 | var fact = ViewBag.Factory as IEntityOperate; 75 | var page = ViewBag.Page as Pager; 76 | 77 | var dic = new Dictionary(); 78 | dic.Add(1, "成功"); 79 | dic.Add(0, "失败"); 80 | 81 | 82 | #line default 83 | #line hidden 84 | WriteLiteral("\r\n\r\n 操作:\r\n"); 95 | 96 | WriteLiteral(" "); 97 | 98 | 99 | #line 16 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 100 | Write(Html.ForDropDownList("action", DeviceHistory.FindAllActionName(), Request["action"], "全部", true)); 101 | 102 | 103 | #line default 104 | #line hidden 105 | WriteLiteral("\r\n\r\n\r\n 结果:\r\n"); 116 | 117 | WriteLiteral(" "); 118 | 119 | 120 | #line 20 "..\..\Areas\WiFi\Views\DeviceHistory\_List_Search.cshtml" 121 | Write(Html.ForDropDownList("success", dic, Request["success"], "全部", true)); 122 | 123 | 124 | #line default 125 | #line hidden 126 | WriteLiteral("\r\n\r\n"); 127 | 128 | } 129 | } 130 | } 131 | #pragma warning restore 1591 132 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/DeviceOnline/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using NewLife.Cube; 4 | @using XCode; 5 | @using WiFi.Entity; 6 | @{ 7 | var fact = ViewBag.Factory as IEntityOperate; 8 | var page = ViewBag.Page as Pager; 9 | } 10 |
11 | 12 | @Html.ForDropDownList("Kind", System.EnumHelper.GetDescriptions(typeof(DeviceKinds)), Request["Kind"], "全部", true) 13 |
14 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/DeviceOnline/_List_Search.generated.cs: -------------------------------------------------------------------------------- 1 | #pragma warning disable 1591 2 | //------------------------------------------------------------------------------ 3 | // 4 | // 此代码由工具生成。 5 | // 运行时版本:4.0.30319.42000 6 | // 7 | // 对此文件的更改可能会导致不正确的行为,并且如果 8 | // 重新生成代码,这些更改将会丢失。 9 | // 10 | //------------------------------------------------------------------------------ 11 | 12 | namespace ASP 13 | { 14 | using System; 15 | using System.Collections.Generic; 16 | using System.IO; 17 | using System.Linq; 18 | using System.Net; 19 | using System.Text; 20 | using System.Web; 21 | using System.Web.Helpers; 22 | using System.Web.Mvc; 23 | using System.Web.Mvc.Ajax; 24 | using System.Web.Mvc.Html; 25 | using System.Web.Routing; 26 | using System.Web.Security; 27 | using System.Web.UI; 28 | using System.Web.WebPages; 29 | 30 | #line 1 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 31 | using NewLife; 32 | 33 | #line default 34 | #line hidden 35 | 36 | #line 3 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 37 | using NewLife.Cube; 38 | 39 | #line default 40 | #line hidden 41 | using NewLife.Reflection; 42 | 43 | #line 2 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 44 | using NewLife.Web; 45 | 46 | #line default 47 | #line hidden 48 | 49 | #line 5 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 50 | using WiFi.Entity; 51 | 52 | #line default 53 | #line hidden 54 | 55 | #line 4 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 56 | using XCode; 57 | 58 | #line default 59 | #line hidden 60 | using XCode.Membership; 61 | 62 | [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "2.0.0.0")] 63 | [System.Web.WebPages.PageVirtualPathAttribute("~/Areas/WiFi/Views/DeviceOnline/_List_Search.cshtml")] 64 | public partial class _Areas_WiFi_Views_DeviceOnline__List_Search_cshtml : System.Web.Mvc.WebViewPage 65 | { 66 | public _Areas_WiFi_Views_DeviceOnline__List_Search_cshtml() 67 | { 68 | } 69 | public override void Execute() 70 | { 71 | 72 | #line 6 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 73 | 74 | var fact = ViewBag.Factory as IEntityOperate; 75 | var page = ViewBag.Page as Pager; 76 | 77 | 78 | #line default 79 | #line hidden 80 | WriteLiteral("\r\n\r\n 类型:\r\n"); 91 | 92 | WriteLiteral(" "); 93 | 94 | 95 | #line 12 "..\..\Areas\WiFi\Views\DeviceOnline\_List_Search.cshtml" 96 | Write(Html.ForDropDownList("Kind", System.EnumHelper.GetDescriptions(typeof(DeviceKinds)), Request["Kind"], "全部", true)); 97 | 98 | 99 | #line default 100 | #line hidden 101 | WriteLiteral("\r\n\r\n"); 102 | 103 | } 104 | } 105 | } 106 | #pragma warning restore 1591 107 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 46 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /WiFi.Web/Areas/WiFi/WiFiAreaRegistration.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Web.Mvc; 3 | using NewLife.Cube; 4 | 5 | namespace WiFi.Device.Web 6 | { 7 | [DisplayName("客流管理")] 8 | public class WiFiAreaRegistration : AreaRegistrationBase 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /WiFi.Web/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="WiFi.Web.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /WiFi.Web/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Mvc; 2 | using System.Web.Routing; 3 | 4 | namespace WiFi.Web 5 | { 6 | // 注意: 有关启用 IIS6 或 IIS7 经典模式的说明, 7 | // 请访问 http://go.microsoft.com/?LinkId=9394801 8 | public class MvcApplication : System.Web.HttpApplication 9 | { 10 | protected void Application_Start() 11 | { 12 | AreaRegistration.RegisterAllAreas(); 13 | 14 | RouteConfig.RegisterRoutes(RouteTable.Routes); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /WiFi.Web/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的常规信息通过下列特性集 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("WiFi客流平台")] 9 | [assembly: AssemblyDescription("采集并存储用户WiFi数据")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyProduct("WiFi.Web")] 12 | [assembly: AssemblyCompany("新生命开发团队")] 13 | [assembly: AssemblyCopyright("Copyright © 新生命开发团队 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | // 对 COM 组件不可见。如果需要从 COM 访问此程序集中的某个类型, 19 | // 请针对该类型将 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("5185f285-2543-4ea7-b27e-2a14811c730e")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 内部版本号 30 | // 修订号 31 | // 32 | // 可以指定所有这些值,也可以使用“修订号”和“内部版本号”的默认值, 33 | // 方法是按如下所示使用“*”: 34 | [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyFileVersion("1.0.2019.0806")] 36 | 37 | /* 38 | * v1.0.2019.0806 轻量版物联网平台 39 | */ 40 | -------------------------------------------------------------------------------- /WiFi.Web/Properties/PublishProfiles/Front.pubxml: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | FileSystem 9 | Release 10 | Any CPU 11 | 12 | True 13 | True 14 | True 15 | False 16 | MergeAllOutputsToASingleAssembly 17 | True 18 | Front 19 | True 20 | True 21 | ..\..\Front\Web 22 | True 23 | 24 | -------------------------------------------------------------------------------- /WiFi.Web/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /WiFi.Web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/WiFi.Web/favicon.ico -------------------------------------------------------------------------------- /WiFi.Web/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /WiFi.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29102.190 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Other", "Other", "{E9E982D4-367F-4305-ABDF-3B590673DADD}" 7 | ProjectSection(SolutionItems) = preProject 8 | Readme.MD = Readme.MD 9 | EndProjectSection 10 | EndProject 11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WiFi.Data", "WiFi.Data\WiFi.Data.csproj", "{7618CB05-1801-4AE3-AEA2-0F94BC6870AC}" 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WiFi.Server", "WiFi.Server\WiFi.Server.csproj", "{654F9F56-A236-4E7F-8B93-B205693A20D9}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WiFi.Web", "WiFi.Web\WiFi.Web.csproj", "{779BC3B7-BA72-4049-837D-3DDC53FBC0A9}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Any CPU = Debug|Any CPU 20 | Release|Any CPU = Release|Any CPU 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {7618CB05-1801-4AE3-AEA2-0F94BC6870AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {7618CB05-1801-4AE3-AEA2-0F94BC6870AC}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {7618CB05-1801-4AE3-AEA2-0F94BC6870AC}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {7618CB05-1801-4AE3-AEA2-0F94BC6870AC}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {654F9F56-A236-4E7F-8B93-B205693A20D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {654F9F56-A236-4E7F-8B93-B205693A20D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {654F9F56-A236-4E7F-8B93-B205693A20D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {654F9F56-A236-4E7F-8B93-B205693A20D9}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Release|Any CPU.Build.0 = Release|Any CPU 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | GlobalSection(ExtensibilityGlobals) = postSolution 40 | SolutionGuid = {E2BACAC2-15CC-4C71-9436-1616D7607684} 41 | EndGlobalSection 42 | EndGlobal 43 | -------------------------------------------------------------------------------- /link.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/link.ico -------------------------------------------------------------------------------- /xLink.Client/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /xLink.Client/Common/MachineInfo.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualBasic.Devices; 2 | using Microsoft.Win32; 3 | using NewLife; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Linq; 8 | using System.Management; 9 | using System.Threading.Tasks; 10 | 11 | namespace xLink.Client 12 | { 13 | /// 硬件助手 14 | public class MachineInfo 15 | { 16 | #region 属性 17 | /// 系统名称 18 | public String OSName { get; } 19 | 20 | /// 系统版本 21 | public String OSVersion { get; } 22 | 23 | /// 处理器序列号 24 | public String Processor { get; } 25 | 26 | /// 处理器序列号 27 | public String CpuID { get; } 28 | 29 | /// 唯一标识 30 | public String UUID { get; } 31 | 32 | /// 机器标识 33 | public String MachineGuid { get; } 34 | 35 | /// 内存总量 36 | public UInt64 Memory { get; } 37 | 38 | /// 可用内存 39 | public UInt64 AvailableMemory => new ComputerInfo().AvailablePhysicalMemory; 40 | 41 | private PerformanceCounter _cpuCounter; 42 | /// CPU占用率 43 | public Single CpuRate => _cpuCounter == null ? 0 : (_cpuCounter.NextValue() / 100); 44 | #endregion 45 | 46 | #region 构造 47 | public MachineInfo() 48 | { 49 | var ci = new ComputerInfo(); 50 | OSName = ci.OSFullName + (Environment.Is64BitOperatingSystem ? " x64" : " x86"); 51 | OSVersion = ci.OSVersion; 52 | 53 | Processor = GetInfo("Win32_Processor", "Name"); 54 | CpuID = GetInfo("Win32_Processor", "ProcessorId"); 55 | Memory = ci.TotalPhysicalMemory; 56 | //AvailableMemory = ci.AvailablePhysicalMemory; 57 | 58 | UUID = GetInfo("Win32_ComputerSystemProduct", "UUID"); 59 | 60 | var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography"); 61 | if (reg != null) 62 | { 63 | MachineGuid = reg.GetValue("MachineGuid") + ""; 64 | } 65 | 66 | // 性能计数器的初始化非常耗时 67 | Task.Run(() => 68 | { 69 | _cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total") 70 | { 71 | MachineName = "." 72 | }; 73 | _cpuCounter.NextValue(); 74 | }); 75 | } 76 | #endregion 77 | 78 | #region WMI辅助 79 | /// 获取WMI信息 80 | /// 81 | /// 82 | /// 83 | public static String GetInfo(String path, String property) 84 | { 85 | // Linux Mono不支持WMI 86 | if (Runtime.Mono) return ""; 87 | 88 | var bbs = new List(); 89 | try 90 | { 91 | var wql = String.Format("Select {0} From {1}", property, path); 92 | var cimobject = new ManagementObjectSearcher(wql); 93 | var moc = cimobject.Get(); 94 | foreach (var mo in moc) 95 | { 96 | if (mo != null && 97 | mo.Properties != null && 98 | mo.Properties[property] != null && 99 | mo.Properties[property].Value != null) 100 | bbs.Add(mo.Properties[property].Value.ToString()); 101 | } 102 | } 103 | catch 104 | { 105 | return ""; 106 | } 107 | 108 | bbs.Sort(); 109 | 110 | return bbs.Distinct().Join(); 111 | } 112 | #endregion 113 | } 114 | } -------------------------------------------------------------------------------- /xLink.Client/FrmDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows.Forms; 4 | 5 | namespace xLink.Client 6 | { 7 | public partial class FrmDevice : Form 8 | { 9 | public LinkClient Client { get; set; } 10 | public Byte[] Data { get; set; } 11 | 12 | public FrmDevice() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | private void FrmDevice_Load(Object sender, EventArgs e) 18 | { 19 | // 初始化数据区 20 | var buf = new Byte[1 + 4]; 21 | buf[0] = (Byte)buf.Length; 22 | 23 | Data = buf; 24 | } 25 | 26 | private async Task Blink(Int32 idx) 27 | { 28 | var b = (Byte)(Data[idx] == 0 ? 1 : 0); 29 | //txtData.Text = Data.ToHex(); 30 | 31 | //var buf = await Client.Write(null, idx, b); 32 | //if (buf != null && buf.Length > 0) 33 | //{ 34 | // Data = buf; 35 | // txtData.Text = buf.ToHex(); 36 | //} 37 | } 38 | 39 | private async void lbLed1_Click(Object sender, EventArgs e) 40 | { 41 | await Blink(1); 42 | } 43 | 44 | private async void lbLed2_Click(Object sender, EventArgs e) 45 | { 46 | await Blink(2); 47 | } 48 | 49 | private async void lbButton1_Click(Object sender, EventArgs e) 50 | { 51 | await Blink(3); 52 | } 53 | 54 | private async void lbButton2_Click(Object sender, EventArgs e) 55 | { 56 | await Blink(4); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /xLink.Client/FrmUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows.Forms; 4 | using NewLife.Log; 5 | 6 | namespace xLink.Client 7 | { 8 | public partial class FrmUser : Form 9 | { 10 | public LinkClient Client { get; set; } 11 | public Byte[] Data { get; set; } 12 | 13 | public FrmUser() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | private void FrmUser_Load(Object sender, EventArgs e) 19 | { 20 | // 初始化数据区 21 | var buf = new Byte[1 + 4]; 22 | buf[0] = (Byte)buf.Length; 23 | 24 | Data = buf; 25 | } 26 | 27 | private async Task Blink(Int32 idx) 28 | { 29 | if (idx >= Data.Length) Data = new Byte[idx + 1]; 30 | var b = (Byte)(Data[idx] == 0 ? 1 : 0); 31 | //txtData.Text = Data.ToHex(); 32 | 33 | //var buf = await Client.Write(txtDevice.Text, idx, b); 34 | //if (buf != null && buf.Length > 0) 35 | //{ 36 | // Data = buf; 37 | // txtData.Text = buf.ToHex(); 38 | //} 39 | } 40 | 41 | private async void lbLed1_Click(Object sender, EventArgs e) 42 | { 43 | var idx = (sender as Control).Tag.ToInt(); 44 | if (idx <= 0) return; 45 | 46 | try 47 | { 48 | await Blink(idx); 49 | } 50 | catch (Exception ex) 51 | { 52 | XTrace.WriteLine(ex.GetTrue().Message); 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /xLink.Client/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Windows.Forms; 4 | using NewLife.Log; 5 | 6 | namespace xLink.Client 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// 应用程序的主入口点。 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | XTrace.UseWinForm(); 17 | 18 | // 降低进程优先级,避免卡死电脑 19 | Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal; 20 | 21 | Application.EnableVisualStyles(); 22 | Application.SetCompatibleTextRenderingDefault(false); 23 | Application.Run(new FrmMain()); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /xLink.Client/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("菲凡物联客户端")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("xLink.Client")] 13 | [assembly: AssemblyCopyright("Copyright © 新生命团队 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("9b82e70b-389d-4328-a5e2-be2837072c38")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 33 | // 方法是按如下所示使用“*”: : 34 | [assembly: AssemblyVersion("3.0.*")] 35 | [assembly: AssemblyFileVersion("3.0.2019.0916")] 36 | 37 | /* 38 | * v3.0.2019.0714 抽象客户端服务端架构 39 | * 40 | * v2.0.2018.1215 升级新版通信框架 41 | * 42 | * v1.0.2017.0316 轻量版物联网平台 43 | */ 44 | -------------------------------------------------------------------------------- /xLink.Client/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace xLink.Client.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("xLink.Client.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /xLink.Client/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace xLink.Client.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /xLink.Client/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /xLink.Client/Properties/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | true 49 | 50 | 51 | 52 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /xLink.Client/Services/DeviceClient.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Net; 3 | using NewLife.Threading; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO.Ports; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace xLink.Client.Services 11 | { 12 | /// 设备客户端 13 | public class DeviceClient : LinkClient 14 | { 15 | #region 属性 16 | #endregion 17 | 18 | #region 构造 19 | /// 实例化 20 | /// 21 | public DeviceClient(String uri) : base(uri) { } 22 | #endregion 23 | 24 | #region 打开 25 | public override Boolean Open() 26 | { 27 | Task.Run(() => _hardInfo = new MachineInfo()); 28 | 29 | return base.Open(); 30 | } 31 | #endregion 32 | 33 | #region 登录 34 | protected override async Task OnLoginAsync(ISocketClient client, Boolean force) 35 | { 36 | var rs = await base.OnLoginAsync(client, force); 37 | 38 | if (rs is IDictionary dic) 39 | { 40 | // 有可能下发设备证书 41 | var dkey = dic["DeviceKey"] + ""; 42 | var dsecret = dic["DeviceSecret"] + ""; 43 | if (!dkey.IsNullOrEmpty()) 44 | { 45 | WriteLog("下发设备证书:{0}/{1}", dkey, dsecret); 46 | 47 | UserName = dkey; 48 | Password = dsecret; 49 | } 50 | } 51 | 52 | return rs; 53 | } 54 | 55 | private MachineInfo _hardInfo; 56 | protected override Object GetLoginInfo() 57 | { 58 | var rs = base.GetLoginInfo().ToDictionary(); 59 | 60 | if (_hardInfo == null) _hardInfo = new MachineInfo(); 61 | 62 | var ps = SerialPort.GetPortNames(); 63 | 64 | // 如果设备编码不存在,则需要提交产品证书 65 | var pkey = ""; 66 | var psecret = ""; 67 | if (UserName.IsNullOrEmpty()) 68 | { 69 | var set = Setting.Current; 70 | pkey = set.ProductKey; 71 | psecret = set.ProductSecret.MD5(); 72 | 73 | WriteLog("动态注册产品:{0}", pkey); 74 | } 75 | 76 | var ext = new 77 | { 78 | ProductKey = pkey, 79 | ProductSecret = psecret, 80 | 81 | _hardInfo.OSName, 82 | _hardInfo.OSVersion, 83 | 84 | _hardInfo.Memory, 85 | _hardInfo.AvailableMemory, 86 | _hardInfo.Processor, 87 | _hardInfo.CpuID, 88 | _hardInfo.CpuRate, 89 | _hardInfo.UUID, 90 | _hardInfo.MachineGuid, 91 | 92 | COMs = ps.Join(","), 93 | }; 94 | 95 | return rs.Merge(ext, true); 96 | } 97 | #endregion 98 | 99 | #region 心跳 100 | protected override Object GetPingInfo() 101 | { 102 | var rs = base.GetPingInfo().ToDictionary(); 103 | 104 | if (_hardInfo == null) _hardInfo = new MachineInfo(); 105 | 106 | var ps = SerialPort.GetPortNames(); 107 | 108 | var ext = new 109 | { 110 | _hardInfo.AvailableMemory, 111 | _hardInfo.CpuRate, 112 | 113 | COMs = ps.Join(","), 114 | 115 | Time = DateTime.Now, 116 | Delay = (Int32)Delay.TotalMilliseconds, 117 | }; 118 | 119 | return rs.Merge(ext, true); 120 | } 121 | #endregion 122 | } 123 | } -------------------------------------------------------------------------------- /xLink.Client/link.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/xLink.Client/link.ico -------------------------------------------------------------------------------- /xLink.Data/Entity/MyModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NewLife.Model; 3 | using xLink.Models; 4 | 5 | namespace xLink.Entity 6 | { 7 | /// 接口 8 | public partial interface IMyModel : IManageUser 9 | { 10 | #region 属性 11 | ///// 唯一编码 12 | //String Code { get; set; } 13 | 14 | /// 类型 15 | String Type { get; set; } 16 | 17 | /// 版本 18 | String Version { get; set; } 19 | 20 | ///// 数据 21 | //String Data { get; set; } 22 | 23 | ///// 注册次数 24 | //Int32 Registers { get; set; } 25 | 26 | ///// 创建者 27 | //Int32 CreateUserID { get; set; } 28 | 29 | ///// 创建时间 30 | //DateTime CreateTime { get; set; } 31 | 32 | ///// 创建地址 33 | //String CreateIP { get; set; } 34 | 35 | ///// 更新者 36 | //Int32 UpdateUserID { get; set; } 37 | 38 | ///// 更新时间 39 | //DateTime UpdateTime { get; set; } 40 | 41 | ///// 更新地址 42 | //String UpdateIP { get; set; } 43 | #endregion 44 | } 45 | 46 | /// 历史接口 47 | public interface IMyHistory : IHistory 48 | { 49 | #region 属性 50 | /// 编号 51 | Int32 ID { get; set; } 52 | 53 | ///// 编码 54 | //Int32 DeviceID { get; set; } 55 | 56 | /// 版本 57 | String Version { get; set; } 58 | 59 | /// 网络类型 60 | String NetType { get; set; } 61 | 62 | ///// 创建者 63 | //Int32 CreateDeviceID { get; set; } 64 | #endregion 65 | } 66 | 67 | /// 在线接口 68 | public interface IMyOnline : IOnline 69 | { 70 | #region 属性 71 | /// 编号 72 | Int32 ID { get; set; } 73 | 74 | ///// 编码 75 | //Int32 DeviceID { get; set; } 76 | 77 | /// 版本 78 | String Version { get; set; } 79 | 80 | /// 网络类型 81 | String NetType { get; set; } 82 | 83 | /// 内网 84 | String InternalUri { get; set; } 85 | 86 | /// 外网 87 | String ExternalUri { get; set; } 88 | 89 | /// 登录 90 | Int32 LoginCount { get; set; } 91 | 92 | /// 心跳 93 | Int32 PingCount { get; set; } 94 | 95 | /// 登录时间 96 | DateTime LoginTime { get; set; } 97 | 98 | /// 错误 99 | Int32 ErrorCount { get; set; } 100 | 101 | /// 最后错误 102 | String LastError { get; set; } 103 | #endregion 104 | } 105 | } -------------------------------------------------------------------------------- /xLink.Data/Entity/用户历史.Biz.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * XCoder v6.9.6298.42194 3 | * 作者:nnhy/X3 4 | * 时间:2017-03-31 21:55:42 5 | * 版权:版权所有 (C) 新生命开发团队 2002~2017 6 | */ 7 | using NewLife; 8 | using NewLife.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.ComponentModel; 12 | using XCode; 13 | using XCode.Cache; 14 | using xLink.Models; 15 | 16 | namespace xLink.Entity 17 | { 18 | /// 用户历史 19 | public partial class UserHistory : Entity, IHistory 20 | { 21 | #region 对象操作 22 | static UserHistory() 23 | { 24 | Meta.Table.DataTable.InsertOnly = true; 25 | } 26 | 27 | ///// 验证数据,通过抛出异常的方式提示验证失败。 28 | ///// 29 | //public override void Valid(Boolean isNew) 30 | //{ 31 | // // 如果没有脏数据,则不需要进行任何处理 32 | // if (!HasDirty) return; 33 | 34 | // // 建议先调用基类方法,基类方法会对唯一索引的数据进行验证 35 | // base.Valid(isNew); 36 | //} 37 | #endregion 38 | 39 | #region 扩展属性 40 | /// 用户 41 | public User User { get { return Extends.Get(nameof(User), k => User.FindByID(UserID)); } } 42 | 43 | /// 用户名 44 | [Map(__.UserID, typeof(User), "ID")] 45 | public String UserName { get { return User + ""; } } 46 | 47 | /// 地址。IP=>Address 48 | [DisplayName("创建地址")] 49 | public String CreateAddress { get { return CreateIP.IPToAddress(); } } 50 | #endregion 51 | 52 | #region 扩展查询 53 | #endregion 54 | 55 | #region 高级查询 56 | /// 高级搜索 57 | /// 58 | /// 59 | /// 60 | /// 61 | /// 62 | /// 63 | /// 64 | /// 65 | public static IList Search(Int32 userid, String action, Int32 result, DateTime start, DateTime end, String key, PageParameter param) 66 | { 67 | var exp = new WhereExpression(); 68 | 69 | if (userid >= 0) exp &= _.UserID == userid; 70 | //if (!type.IsNullOrEmpty()) exp &= _.Type == type; 71 | if (!action.IsNullOrEmpty()) exp &= _.Action == action; 72 | if (result == 0) 73 | exp &= _.Success == false; 74 | else if (result == 1) 75 | exp &= _.Success == true; 76 | 77 | exp &= _.CreateTime.Between(start, end); 78 | 79 | if (!key.IsNullOrEmpty()) 80 | exp &= (_.Name.Contains(key) | _.Remark.Contains(key) | _.CreateIP.Contains(key)); 81 | 82 | return FindAll(exp, param); 83 | } 84 | #endregion 85 | 86 | #region 扩展操作 87 | /// 类别名实体缓存,异步,缓存10分钟 88 | static FieldCache ActionCache = new FieldCache(_.Action); 89 | 90 | /// 获取所有类别名称 91 | /// 92 | public static IDictionary FindAllActionName() 93 | { 94 | return ActionCache.FindAllName(); 95 | } 96 | #endregion 97 | 98 | #region 业务 99 | #endregion 100 | } 101 | } -------------------------------------------------------------------------------- /xLink.Data/Entity/用户在线.Biz.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * XCoder v6.9.6298.42194 3 | * 作者:nnhy/X3 4 | * 时间:2017-03-31 21:55:42 5 | * 版权:版权所有 (C) 新生命开发团队 2002~2017 6 | */ 7 | using NewLife; 8 | using NewLife.Data; 9 | using System; 10 | using System.Collections.Generic; 11 | using System.ComponentModel; 12 | using XCode; 13 | using XCode.Cache; 14 | using XCode.Membership; 15 | using xLink.Models; 16 | 17 | namespace xLink.Entity 18 | { 19 | /// 用户在线 20 | public partial class UserOnline : Entity, IOnline 21 | { 22 | #region 对象操作 23 | static UserOnline() 24 | { 25 | var df = Meta.Factory.AdditionalFields; 26 | df.Add(__.LoginCount); 27 | df.Add(__.PingCount); 28 | 29 | Meta.Modules.Add(); 30 | Meta.Modules.Add(); 31 | 32 | var sc = Meta.SingleCache; 33 | sc.FindSlaveKeyMethod = k => Find(_.SessionID == k); 34 | sc.GetSlaveKeyMethod = e => e.SessionID; 35 | } 36 | #endregion 37 | 38 | #region 扩展属性 39 | /// 用户 40 | public User User => Extends.Get(nameof(User), k => User.FindByID(UserID)); 41 | 42 | /// 用户名 43 | [Map(__.UserID)] 44 | public String UserName => User + ""; 45 | 46 | /// 地址。IP=>Address 47 | [DisplayName("地址")] 48 | public String ExternalAddress => ExternalUri.IPToAddress(); 49 | #endregion 50 | 51 | #region 扩展查询 52 | /// 根据会话查找 53 | /// 会话 54 | /// 是否走缓存 55 | /// 56 | public static UserOnline FindBySessionID(String sessionid, Boolean cache = true) 57 | { 58 | if (!cache) return Find(_.SessionID == sessionid); 59 | 60 | return Meta.SingleCache.GetItemWithSlaveKey(sessionid) as UserOnline; 61 | } 62 | #endregion 63 | 64 | #region 高级查询 65 | /// 查询满足条件的记录集,分页、排序 66 | /// 类型 67 | /// 开始时间 68 | /// 结束时间 69 | /// 关键字 70 | /// 分页排序参数,同时返回满足条件的总记录数 71 | /// 实体集 72 | public static IList Search(String type, DateTime start, DateTime end, String key, PageParameter param) 73 | { 74 | var exp = new WhereExpression(); 75 | 76 | //if (!type.IsNullOrEmpty()) exp &= _.Type == type; 77 | 78 | exp &= _.CreateTime.Between(start, end); 79 | 80 | if (!key.IsNullOrEmpty()) 81 | exp &= (_.Name.Contains(key) | _.InternalUri.Contains(key) | _.ExternalUri.Contains(key)); 82 | 83 | return FindAll(exp, param); 84 | } 85 | #endregion 86 | 87 | #region 扩展操作 88 | /// 获取 或 添加 89 | /// 90 | /// 91 | public static UserOnline GetOrAdd(String sessionId) => GetOrAdd(sessionId, FindBySessionID, k => new UserOnline { SessionID = k }); 92 | #endregion 93 | 94 | #region 业务 95 | /// 删除过期,指定过期时间 96 | /// 超时时间,秒 97 | /// 98 | public static IList ClearExpire(Int32 secTimeout) 99 | { 100 | // 10分钟不活跃将会被删除 101 | var exp = _.UpdateTime < DateTime.Now.AddSeconds(-secTimeout); 102 | var list = FindAll(exp, null, null, 0, 0); 103 | list.Delete(); 104 | 105 | return list; 106 | } 107 | #endregion 108 | } 109 | } -------------------------------------------------------------------------------- /xLink.Data/LinkServer.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Log; 3 | using NewLife.Net; 4 | using NewLife.Remoting; 5 | using NewLife.Threading; 6 | using System; 7 | using System.Collections.Generic; 8 | using xLink.Services; 9 | 10 | namespace xLink 11 | { 12 | /// 物联服务器 13 | /// 14 | /// 物联服务器,用于承载继承自LinkService的服务接口,并衍生出LinkSession以管理长连接状态。 15 | /// 服务层是无状态架构,每次请求都会实例化LinkService新实例,LinkService每次接受新连接后,都创建新的LinkSession会话,在多次请求中共享。 16 | /// 17 | public class LinkServer : ApiServer 18 | { 19 | #region 属性 20 | /// 会话超时时间。超过该时间将删除会话,默认20*60秒 21 | public Int32 SessionTimeout { get; set; } 22 | 23 | private IList _services = new List(); 24 | #endregion 25 | 26 | #region 构造 27 | /// 实例化令牌服务器 28 | public LinkServer() 29 | { 30 | Port = 2233; 31 | Log = XTrace.Log; 32 | 33 | StatPeriod = 60; 34 | ShowError = true; 35 | 36 | // 使用Socket层会话超时时间 37 | SessionTimeout = NewLife.Net.Setting.Current.SessionTimeout; 38 | 39 | #if DEBUG 40 | EncoderLog = XTrace.Log; 41 | StatPeriod = 10; 42 | #endif 43 | } 44 | 45 | /// 销毁 46 | /// 47 | protected override void OnDispose(Boolean disposing) 48 | { 49 | base.OnDispose(disposing); 50 | 51 | _expireTimer.TryDispose(); 52 | _expireTimer = null; 53 | } 54 | #endregion 55 | 56 | #region 方法 57 | /// 启动 58 | public override void Start() 59 | { 60 | var svr = EnsureCreate(); 61 | svr.Log = Log; 62 | 63 | base.Start(); 64 | 65 | // 每次上线清空一次在线表 66 | _expireTimer = new TimerX(CheckExpire, null, 0, 60_000) { Async = true }; 67 | } 68 | 69 | /// 添加物联服务 70 | /// 71 | public void Add() where TService : class, ILinkService, new() 72 | { 73 | var svc = new TService(); 74 | 75 | // 注册服务接口 76 | Register(); 77 | 78 | // 记录服务,用于清理过期等操作 79 | _services.Add(svc); 80 | } 81 | #endregion 82 | 83 | #region 过期清理 84 | TimerX _expireTimer; 85 | void CheckExpire(Object state) 86 | { 87 | var timeout = SessionTimeout; 88 | if (timeout <= 0) return; 89 | 90 | foreach (var svc in _services) 91 | { 92 | svc.ClearExpire(timeout); 93 | } 94 | } 95 | 96 | /// 删除过期会话 97 | /// 会话ID 98 | /// 99 | public Int32 ClearExpire(Int32[] ids) 100 | { 101 | if (ids.Length == 0) return 0; 102 | 103 | if (!(Server is NetServer svr)) return 0; 104 | 105 | foreach (var item in ids) 106 | { 107 | var ss = svr.GetSession(item); 108 | if (ss != null) ss.TryDispose(); 109 | } 110 | 111 | return ids.Length; 112 | } 113 | #endregion 114 | 115 | #region 辅助 116 | /// 设置内部日志是否开启 117 | /// 是否开启会话级日志 118 | /// 是否开启Socket级日志 119 | /// 是否显示编码日志 120 | public void SetLog(Boolean session, Boolean socket, Boolean encoder = false) 121 | { 122 | if (!(Server is NetServer svr)) return; 123 | 124 | // 置空可以让其使用当前Log日志 125 | svr.SessionLog = session ? null : Logger.Null; 126 | svr.SocketLog = socket ? null : Logger.Null; 127 | 128 | //if (Encoder != null) Encoder.Log = Log; 129 | if (encoder) EncoderLog = Log; 130 | } 131 | #endregion 132 | } 133 | } -------------------------------------------------------------------------------- /xLink.Data/Services/LinkService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using NewLife.Net; 5 | using NewLife.Remoting; 6 | using XCode; 7 | 8 | namespace xLink.Services 9 | { 10 | /// 物联服务接口 11 | public interface ILinkService 12 | { 13 | /// 清理超时会话 14 | /// 15 | /// 16 | Int32 ClearExpire(Int32 secTimeout); 17 | } 18 | 19 | /// 物联服务 20 | public abstract class LinkService : ILinkService, IApi 21 | { 22 | #region 属性 23 | /// 接口会话 24 | public IApiSession Session { get; set; } 25 | 26 | /// 请求参数 27 | public IDictionary Parameters { get; set; } 28 | #endregion 29 | 30 | #region 登录 31 | #endregion 32 | 33 | #region 心跳 34 | #endregion 35 | 36 | #region 清理超时 37 | /// 清理超时会话 38 | /// 39 | /// 40 | public virtual Int32 ClearExpire(Int32 secTimeout) => 0; 41 | #endregion 42 | 43 | #region 异常处理 44 | /// 抛出异常 45 | /// 46 | /// 47 | /// 48 | /// 49 | protected ApiException Error(Int32 errCode, String msg, Object result = null) 50 | { 51 | var ex = new ApiException(errCode, msg); 52 | if (result != null) 53 | { 54 | // 支持自定义类型 55 | foreach (var item in result.ToDictionary()) 56 | { 57 | ex.Data[item.Key] = item.Value; 58 | } 59 | } 60 | 61 | return ex; 62 | } 63 | #endregion 64 | 65 | #region 辅助 66 | /// 写日志 67 | /// 68 | /// 69 | protected void WriteLog(String format, params Object[] args) 70 | { 71 | var ns = Session as NetSession; 72 | ns?.WriteLog(format, args); 73 | } 74 | #endregion 75 | } 76 | } -------------------------------------------------------------------------------- /xLink.Data/XCoder.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" hostSpecific="true" debug="true" #> 2 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\NewLife.Core.dll" #> 3 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\XCode.dll" #> 4 | <#@ import namespace="System.Diagnostics" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="XCode.Code" #> 7 | <#@ output extension=".log" #> 8 | <# 9 | // 设置当前工作目录 10 | PathHelper.BasePath = Host.ResolvePath("."); 11 | // 导入模型文件并生成实体类,模型文件、输出目录、命名空间、连接名、中文文件名、表名字段名大小写 12 | //EntityBuilder.Build(String xmlFile = null, String output = null, String nameSpace = null, String connName = null, Boolean? chineseFileName = true,Boolean? nameIgnoreCase = null); 13 | EntityBuilder.Build(); 14 | 15 | //var tables = DAL.ImportFrom("Company.Project.xml"); 16 | //EntityBuilder.Build(tables); 17 | #> -------------------------------------------------------------------------------- /xLink.Data/xLink.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net45;netcoreapp2.1;net40 5 | 3.1.2020.0708 6 | 3.1.2020.0708 7 | 3.1.* 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | XCoder.tt 18 | True 19 | True 20 | 21 | 22 | XCoder.log 23 | TextTemplatingFileGenerator 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /xLink.HttpServer/Common/ApiFilterAttribute.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.Filters; 3 | using NewLife.Log; 4 | using System; 5 | using System.Linq; 6 | 7 | namespace xLinkServer.Common 8 | { 9 | /// 统一Api过滤处理 10 | public sealed class ApiFilterAttribute : ActionFilterAttribute 11 | { 12 | /// 执行前,验证模型 13 | /// 14 | public override void OnActionExecuting(ActionExecutingContext context) 15 | { 16 | if (!context.ModelState.IsValid) 17 | throw new ApplicationException(context.ModelState.Values.First(p => p.Errors.Count > 0).Errors[0].ErrorMessage); 18 | 19 | base.OnActionExecuting(context); 20 | } 21 | 22 | /// 执行后,包装结果和异常 23 | /// 24 | public override void OnActionExecuted(ActionExecutedContext context) 25 | { 26 | if (context.Result != null) 27 | { 28 | if (context.Result is ObjectResult obj) 29 | { 30 | context.Result = new JsonResult(new { code = 0, data = obj.Value }); 31 | } 32 | else if (context.Result is EmptyResult) 33 | { 34 | context.Result = new JsonResult(new { code = 0, data = new { } }); 35 | } 36 | } 37 | else if (context.Exception != null && !context.ExceptionHandled) 38 | { 39 | var ex = context.Exception.GetTrue(); 40 | if (ex is NewLife.Remoting.ApiException aex) 41 | context.Result = new JsonResult(new { code = aex.Code, data = aex.Message }); 42 | else 43 | context.Result = new JsonResult(new { code = 500, data = ex.Message }); 44 | 45 | context.ExceptionHandled = true; 46 | 47 | // 输出异常日志 48 | if (XTrace.Debug) XTrace.WriteException(ex); 49 | } 50 | 51 | base.OnActionExecuted(context); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Common/DateTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | namespace xLinkServer.Common 6 | { 7 | public class DateTimeConverter : JsonConverter 8 | { 9 | public String DateTimeFormat { get; set; } = "yyyy-MM-dd HH:mm:ss"; 10 | 11 | public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 12 | { 13 | return reader.GetString().ToDateTime(); 14 | //return DateTime.Parse(reader.GetString()); 15 | } 16 | 17 | public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) 18 | { 19 | writer.WriteStringValue(value.ToString(DateTimeFormat)); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Common/RequestExt.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using Microsoft.AspNetCore.Http.Extensions; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace xLinkServer.Common 9 | { 10 | public static class RequestExt 11 | { 12 | 13 | public static Uri GetRawUrl(this HttpRequest request) 14 | { 15 | string encodedUrl = request.GetEncodedUrl(); 16 | return new Uri(encodedUrl); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /xLink.HttpServer/Common/TokenFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Filters; 2 | using NewLife; 3 | using NewLife.Log; 4 | using NewLife.Remoting; 5 | using System; 6 | using xLinkServer.Controllers; 7 | 8 | namespace xLinkServer.Common 9 | { 10 | /// 令牌校验 11 | public class TokenFilterAttribute : ActionFilterAttribute 12 | { 13 | public override void OnActionExecuting(ActionExecutingContext context) 14 | { 15 | if (context.Controller is BaseController bc) 16 | { 17 | var path = getPath(context); 18 | var session = bc.Session; 19 | if (bc.Token.IsNullOrEmpty()) throw new ApiException(403, "未授权"); 20 | if (session == null) 21 | { 22 | XTrace.WriteLine($"令牌无效:{bc.Token} {path}"); 23 | throw new ApiException(402, "令牌无效"); 24 | } 25 | 26 | if (context.Controller is DeviceController) 27 | { 28 | if (session["Device"] == null) 29 | { 30 | XTrace.WriteLine($"设备未登录:{bc.Token} {path}"); 31 | throw new ApiException(500, "设备未登录"); 32 | } 33 | } 34 | else 35 | { 36 | if (session["User"] == null) 37 | { 38 | 39 | XTrace.WriteLine($"用户未登录:{bc.Token} {path}"); 40 | throw new ApiException(500, "用户未登录"); 41 | } 42 | } 43 | } 44 | 45 | base.OnActionExecuting(context); 46 | } 47 | 48 | private static String getPath(ActionExecutingContext context) 49 | { 50 | try 51 | { 52 | var path = context.HttpContext.Request.Path; 53 | if (path.HasValue) return path.Value; 54 | } 55 | catch (Exception ex) 56 | { 57 | XTrace.WriteException(ex); 58 | } 59 | return ""; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Common/TokenSession.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Caching; 3 | using NewLife.Collections; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace xLinkServer.Common 8 | { 9 | public class TokenSession 10 | { 11 | /// 有效期 12 | public TimeSpan Expire { get; set; } = TimeSpan.FromMinutes(20); 13 | 14 | /// 会话存储 15 | public ICache Cache { get; set; } = new MemoryCache { Expire = 20 * 60, Period = 60 * 10 }; 16 | 17 | /// 创建新的Session 18 | /// 19 | /// 20 | public IDictionary CreateSession(String token) 21 | { 22 | var key = GetKey(token); 23 | var dic = Cache.GetDictionary(key); 24 | Cache.SetExpire(key, Expire); 25 | 26 | //!! 临时修正可空字典的BUG 27 | if (Cache is MemoryCache mc) 28 | { 29 | dic = new NullableDictionary(); 30 | mc.Set(key, dic); 31 | } 32 | 33 | return dic; 34 | } 35 | 36 | /// 根据Token获取session 37 | /// 38 | /// 39 | public IDictionary GetSession(String token) 40 | { 41 | if (token.IsNullOrEmpty()) return null; 42 | 43 | var key = GetKey(token); 44 | // 当前缓存没有指定的token 则直接返回null 45 | if (!Cache.ContainsKey(key)) return null; 46 | 47 | // 采用哈希结构。内存缓存用并行字段,Redis用Set 48 | var dic = Cache.GetDictionary(key); 49 | Cache.SetExpire(key, Expire); 50 | 51 | return dic; 52 | } 53 | 54 | /// 55 | /// 刷新token有效期 56 | /// 57 | /// 58 | /// 59 | public IDictionary CopySession(String token, String newToken) 60 | { 61 | if (newToken.IsNullOrEmpty()) return null; 62 | 63 | var dic = GetSession(token); 64 | if (dic != null) 65 | { 66 | var nkey = GetKey(newToken); 67 | if (Cache is MemoryCache mc) 68 | { 69 | mc.Set(nkey, dic, Expire); 70 | } 71 | else 72 | { 73 | var ndic = CreateSession(newToken); 74 | foreach (var item in dic) 75 | { 76 | ndic[item.Key] = item.Value; 77 | } 78 | } 79 | } 80 | 81 | // 确保建立新的 82 | return GetSession(newToken); 83 | } 84 | 85 | /// 根据令牌活期缓存Key 86 | /// 87 | /// 88 | protected virtual String GetKey(String token) => (!token.IsNullOrEmpty() && token.Length > 16) ? token.MD5() : token; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /xLink.HttpServer/Common/WebHelper.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using NewLife; 3 | using System; 4 | 5 | namespace xLinkServer 6 | { 7 | /// Web助手 8 | public static class WebHelper 9 | { 10 | /// 获取用户主机 11 | /// 12 | /// 13 | public static String GetUserHost(this HttpContext context) 14 | { 15 | var request = context.Request; 16 | 17 | var str = ""; 18 | if (str.IsNullOrEmpty()) str = request.Headers["HTTP_X_FORWARDED_FOR"]; 19 | if (str.IsNullOrEmpty()) str = request.Headers["X-Real-IP"]; 20 | if (str.IsNullOrEmpty()) str = request.Headers["X-Forwarded-For"]; 21 | if (str.IsNullOrEmpty()) str = request.Headers["REMOTE_ADDR"]; 22 | //if (str.IsNullOrEmpty()) str = request.Headers["Host"]; 23 | //if (str.IsNullOrEmpty()) str = context.Connection?.RemoteIpAddress?.MapToIPv4() + ""; 24 | if (str.IsNullOrEmpty()) 25 | { 26 | var addr = context.Connection?.RemoteIpAddress; 27 | if (addr != null) 28 | { 29 | if (addr.IsIPv4MappedToIPv6) addr = addr.MapToIPv4(); 30 | str = addr + ""; 31 | } 32 | } 33 | 34 | return str; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Common/XLogger.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using Microsoft.Extensions.DependencyInjection.Extensions; 3 | using Microsoft.Extensions.Logging; 4 | using NewLife; 5 | using System; 6 | 7 | namespace xLinkServer.Common 8 | { 9 | static class XLoggerExtensions 10 | { 11 | public static ILoggingBuilder AddXLog(this ILoggingBuilder builder) 12 | { 13 | builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton()); 14 | 15 | return builder; 16 | } 17 | } 18 | 19 | [ProviderAlias("XLog")] 20 | class XLoggerProvider : ILoggerProvider 21 | { 22 | public ILogger CreateLogger(String categoryName) 23 | { 24 | var log = NewLife.Log.XTrace.Log; 25 | if (log is NewLife.Log.CompositeLog cp) 26 | { 27 | var tf = cp.Get(); 28 | if (tf != null) log = tf; 29 | } 30 | 31 | return new XLogger { Logger = log }; 32 | } 33 | 34 | public void Dispose() { } 35 | } 36 | 37 | class XLogger : ILogger 38 | { 39 | public NewLife.Log.ILog Logger { get; set; } 40 | 41 | public IDisposable BeginScope(TState state) 42 | { 43 | return null; 44 | } 45 | 46 | public Boolean IsEnabled(LogLevel logLevel) 47 | { 48 | return Logger.Enable; 49 | } 50 | 51 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) 52 | { 53 | if (!Logger.Enable) return; 54 | 55 | if (formatter == null) throw new ArgumentNullException(nameof(formatter)); 56 | 57 | var txt = formatter(state, exception); 58 | if (txt.IsNullOrEmpty() && exception == null) return; 59 | 60 | switch (logLevel) 61 | { 62 | case LogLevel.Trace: 63 | case LogLevel.Debug: 64 | Logger.Debug(txt); 65 | break; 66 | case LogLevel.Information: 67 | Logger.Info(txt); 68 | break; 69 | case LogLevel.Warning: 70 | Logger.Warn(txt); 71 | break; 72 | case LogLevel.Error: 73 | Logger.Error(txt); 74 | break; 75 | case LogLevel.Critical: 76 | Logger.Fatal(txt); 77 | break; 78 | case LogLevel.None: 79 | break; 80 | default: 81 | break; 82 | } 83 | 84 | if (exception != null) Logger.Error("{0}", exception); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Models/ConfigModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLinkServer.Models 4 | { 5 | /// 配置模型 6 | public class ConfigModel 7 | { 8 | /// 配置名 9 | public String Name { get; set; } 10 | 11 | /// 配置字符串,json格式 12 | public String Config { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Hosting; 5 | using NewLife.Log; 6 | using XCode.DataAccessLayer; 7 | using xLink.Entity; 8 | using xLinkServer.Common; 9 | using xLinkServer.Services; 10 | 11 | namespace xLinkServer 12 | { 13 | public class Program 14 | { 15 | public static void Main(String[] args) 16 | { 17 | XTrace.UseConsole(); 18 | 19 | // 异步初始化 20 | Task.Run(InitAsync); 21 | 22 | CreateHostBuilder(args).Build().Run(); 23 | } 24 | 25 | public static IHostBuilder CreateHostBuilder(String[] args) 26 | { 27 | return Host.CreateDefaultBuilder(args) 28 | .ConfigureLogging(logging => { logging.AddXLog(); }) 29 | .ConfigureWebHostDefaults(webBuilder => 30 | { 31 | webBuilder.UseStartup(); 32 | }); 33 | } 34 | 35 | private static DeviceOnlineService _online; 36 | private static void InitAsync() 37 | { 38 | // 配置 39 | var set = NewLife.Common.SysConfig.Current; 40 | if (set.Name == "NewLife.Cube" || set.DisplayName == "魔方平台") 41 | { 42 | set.Name = "xLinkServer"; 43 | set.DisplayName = "物联网平台"; 44 | 45 | set.Save(); 46 | } 47 | 48 | #if !DEBUG 49 | var set2 = XCode.Setting.Current; 50 | if (set2.IsNew) 51 | { 52 | set2.ShowSQL = false; 53 | 54 | set2.Save(); 55 | } 56 | #endif 57 | 58 | var set3 = Setting.Current; 59 | 60 | // 初始化数据库 61 | var n = Device.Meta.Count; 62 | 63 | // 设备在线管理服务 64 | var svc = new DeviceOnlineService(); 65 | svc.Init(); 66 | _online = svc; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:51047/", 7 | "sslPort": 44308 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "xLink.HttpServer": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Services/DeviceOnlineService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NewLife; 3 | using NewLife.Threading; 4 | using xLink.Entity; 5 | 6 | namespace xLinkServer.Services 7 | { 8 | /// 设备在线服务 9 | public class DeviceOnlineService : DisposeBase 10 | { 11 | #region 属性 12 | #endregion 13 | 14 | #region 构造 15 | protected override void Dispose(Boolean disposing) 16 | { 17 | base.Dispose(disposing); 18 | 19 | _timer.TryDispose(); 20 | } 21 | #endregion 22 | 23 | #region 方法 24 | public void Init() => _timer = new TimerX(CheckOnline, null, 5_000, 30_000) { Async = true }; 25 | 26 | private TimerX _timer; 27 | private void CheckOnline(Object state) 28 | { 29 | var set = Setting.Current; 30 | if (set.SessionTimeout > 0) 31 | { 32 | var rs = DeviceOnline.ClearExpire(set.SessionTimeout); 33 | if (rs != null) 34 | { 35 | foreach (var olt in rs) 36 | { 37 | var dv = olt?.Device; 38 | var msg = "[{0}]]登录于{1},最后活跃于{2}".F(dv, olt.CreateTime, olt.UpdateTime); 39 | DeviceHistory.Create(dv, "超时下线", true, msg, set.NodeName, olt.CreateIP); 40 | 41 | if (dv != null) 42 | { 43 | // 计算在线时长 44 | if (olt.CreateTime.Year > 2000 && olt.UpdateTime.Year > 2000) 45 | { 46 | dv.OnlineTime += (Int32)(olt.UpdateTime - olt.CreateTime).TotalSeconds; 47 | dv.SaveAsync(); 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | #endregion 55 | } 56 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Services/TokenService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using NewLife; 6 | 7 | namespace xLinkServer.Services 8 | { 9 | /// 10 | /// 11 | /// 12 | public class TokenService 13 | { 14 | /// 15 | /// item1=设备code 16 | /// item2=用户Code 17 | /// Token无效返回null 18 | /// 19 | /// 20 | /// 21 | public static Tuple ParseToken(String token) 22 | { 23 | var str = token.Trim().Substring(null, "."); 24 | if (str.IsNullOrEmpty()) return null; 25 | str = str.ToBase64().ToStr(); 26 | if (str.IsNullOrEmpty()) return null; 27 | 28 | var rlist = str.Split('#', ','); 29 | var deviceCode = ""; 30 | var userCode = ""; 31 | if (rlist.Length > 0) 32 | { 33 | deviceCode = rlist[0]; 34 | } 35 | 36 | if (rlist.Length > 1) 37 | { 38 | userCode = rlist[1]; 39 | } 40 | 41 | return Tuple.Create(deviceCode, userCode); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /xLink.HttpServer/Setting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using NewLife; 4 | using NewLife.Configuration; 5 | 6 | namespace xLinkServer 7 | { 8 | /// 扫描服务配置 9 | [Config("xLinkServer.config")] 10 | public class Setting : Config 11 | { 12 | /// 节点名称。默认本地计算机名 13 | [Description("节点名称。默认本地计算机名")] 14 | public String NodeName { get; set; } 15 | 16 | /// 令牌有效期。默认12*3600秒 17 | [Description("令牌有效期。默认12*3600秒")] 18 | public Int32 TokenExpire { get; set; } = 12 * 3600; 19 | 20 | /// 会话超时。默认600秒 21 | [Description("会话超时。默认600秒")] 22 | public Int32 SessionTimeout { get; set; } = 600; 23 | 24 | /// 自动注册。允许客户端自动注册,默认true 25 | [Description("自动注册。允许客户端自动注册,默认true")] 26 | public Boolean AutoRegister { get; set; } = true; 27 | 28 | protected override void OnLoaded() 29 | { 30 | if (NodeName.IsNullOrEmpty()) NodeName = Environment.MachineName; 31 | 32 | base.OnLoaded(); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /xLink.HttpServer/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Encodings.Web; 3 | using System.Text.Unicode; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | using NewLife.Caching; 10 | using xLinkServer.Common; 11 | using xLinkServer.Services; 12 | 13 | namespace xLinkServer 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | services.AddHttpClient(); 28 | 29 | // 队列服务,用于功能模块之间交互 30 | var qs = new QueueService { Cache = MemoryCache.Default }; 31 | services.AddSingleton(qs); 32 | 33 | services.AddControllers() 34 | .AddJsonOptions(options => 35 | { 36 | options.JsonSerializerOptions.Converters.Add(new DateTimeConverter()); 37 | options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); 38 | }); 39 | } 40 | 41 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 42 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 43 | { 44 | if (env.IsDevelopment()) 45 | { 46 | app.UseDeveloperExceptionPage(); 47 | } 48 | 49 | //app.UseHttpsRedirection(); 50 | 51 | app.UseRouting(); 52 | 53 | app.UseAuthorization(); 54 | 55 | app.UseEndpoints(endpoints => 56 | { 57 | endpoints.MapControllers(); 58 | }); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /xLink.HttpServer/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "Port": 2234, 10 | "AllowedHosts": "*", 11 | "ConnectionStrings": { 12 | "xLink": { 13 | "connectionString": "Data Source=..\\Data\\xLink.db", 14 | "providerName": "SQLite" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /xLink.HttpServer/xLink.HttpServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | xLinkServer 6 | xLinkServer 7 | 物联网服务端 8 | 物联网平台 9 | 新生命开发团队 10 | 版权所有(C) 新生命开发团队 2002~2025 11 | 3.1.2020.0708 12 | 3.1.2020.0708 13 | 3.1.* 14 | false 15 | ..\Bin\HttpServer 16 | false 17 | pdbonly 18 | true 19 | TRACE 20 | latest 21 | 22 | 23 | 24 | $(DefineConstants);DEBUG 25 | full 26 | false 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | PreserveNewest 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /xLink.Server/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /xLink.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Agent; 3 | using NewLife.Log; 4 | using NewLife.Threading; 5 | using System; 6 | using xLink.Services; 7 | 8 | namespace xLink 9 | { 10 | class Program 11 | { 12 | static void Main(String[] args) => new MyService().Main(args); 13 | } 14 | 15 | class MyService : ServiceBase 16 | { 17 | /// 构造函数 18 | public MyService() 19 | { 20 | ServiceName = "LinkServer"; 21 | 22 | // 异步初始化数据 23 | ThreadPoolX.QueueUserWorkItem(() => 24 | { 25 | var set = XCode.Setting.Current; 26 | if (set.IsNew) 27 | { 28 | set.Debug = false; 29 | set.ShowSQL = false; 30 | set.Save(); 31 | } 32 | }); 33 | } 34 | 35 | /// 服务器 36 | LinkServer Svr; 37 | 38 | /// 启动工作 39 | protected override void StartWork(String reason) 40 | { 41 | base.StartWork(reason); 42 | 43 | var set = Setting.Current; 44 | 45 | // 实例化服务器 46 | var svr = new LinkServer 47 | { 48 | Name = "平台", 49 | Port = set.Port, 50 | }; 51 | svr.Log = XTrace.Log; 52 | svr.SetLog(set.Debug, set.SocketDebug, set.EncoderDebug); 53 | 54 | // 遍历注册各服务控制器 55 | svr.Add(); 56 | svr.Add(); 57 | 58 | svr.Start(); 59 | 60 | Svr = svr; 61 | } 62 | 63 | /// 停止工作 64 | protected override void StopWork(String reason) 65 | { 66 | Svr.TryDispose(); 67 | Svr = null; 68 | 69 | base.StopWork(reason); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /xLink.Server/Setting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using NewLife.Xml; 4 | 5 | namespace xLink 6 | { 7 | /// 配置 8 | [XmlConfigFile("Config/Server.config", 15000)] 9 | public class Setting : XmlConfig 10 | { 11 | #region 属性 12 | /// 调试开关。默认true 13 | [Description("调试开关。默认true")] 14 | public Boolean Debug { get; set; } = true; 15 | 16 | /// 端口。默认2233 17 | [Description("端口。默认2233")] 18 | public Int32 Port { get; set; } = 2233; 19 | 20 | /// 网络日志开关。默认false 21 | [Description("网络日志开关。默认false")] 22 | public Boolean SocketDebug { get; set; } 23 | 24 | /// 编码日志开关。默认false 25 | [Description("编码日志开关。默认false")] 26 | public Boolean EncoderDebug { get; set; } 27 | #endregion 28 | 29 | #region 构造 30 | /// 实例化 31 | public Setting() 32 | { 33 | #if DEBUG 34 | EncoderDebug = true; 35 | #endif 36 | } 37 | #endregion 38 | } 39 | } -------------------------------------------------------------------------------- /xLink.Server/link.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/xLink.Server/link.ico -------------------------------------------------------------------------------- /xLink.Server/xLink.Server.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net45;netcoreapp2.1;net40 6 | xLinkServer 7 | 物联网服务端 8 | 物联网平台,负责在硬件设备以及用户端之间交互数据指令 9 | 新生命开发团队 10 | 版权所有(C) 新生命开发团队 2002~2025 11 | 3.1.2020.0708 12 | 3.1.2020.0708 13 | 3.1.* 14 | false 15 | link.ico 16 | ..\Bin\RpcServer 17 | pdbonly 18 | true 19 | TRACE 20 | 21 | 22 | 23 | $(DefineConstants);NETSTANDARD2_0;__CORE__ 24 | 25 | 26 | 27 | $(DefineConstants);__WIN__ 28 | 29 | 30 | 31 | $(DefineConstants);__WIN__;NET4 32 | 33 | 34 | 35 | $(DefineConstants);DEBUG 36 | full 37 | false 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/DeviceCommandController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using Microsoft.AspNetCore.Mvc; 6 | using NewLife.Cube; 7 | using NewLife.Web; 8 | using XCode.Membership; 9 | using xLink.Entity; 10 | 11 | namespace xLink.Web.Areas.Devices.Controllers 12 | { 13 | [DevicesArea] 14 | [DisplayName("设备命令")] 15 | public class DeviceCommandController : EntityController 16 | { 17 | static DeviceCommandController() => MenuOrder = 58; 18 | 19 | protected override IEnumerable Search(Pager p) 20 | { 21 | var cityId = p["cityId"].ToInt(-1); 22 | var deviceId = p["deviceId"].ToInt(-1); 23 | var command = p["command"]; 24 | 25 | var start = p["dtStart"].ToDateTime(); 26 | var end = p["dtEnd"].ToDateTime(); 27 | 28 | return DeviceCommand.Search(cityId, deviceId, command, start, end, p["Q"], p); 29 | } 30 | 31 | [EntityAuthorize(PermissionFlags.Update)] 32 | public ActionResult Download(Int32 Id) 33 | { 34 | var device = DeviceCommand.FindByID(Id); 35 | if (device == null) throw new Exception("找不到ID!"); 36 | 37 | var tmpPath = (device.Result).GetFullPath(); 38 | var fi = new FileInfo(tmpPath); 39 | 40 | if (!fi.Exists) return JsonRefresh("下载文件不存在!"); 41 | 42 | var bytes = new byte[fi.Length]; 43 | using (var fs = fi.OpenRead()) 44 | { 45 | fs.Read(bytes, 0, bytes.Length); 46 | } 47 | 48 | return File(bytes, "application/octet-stream", fi.Name); 49 | //System.IO.File.Copy(tmpPath, tmpPath, true); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/DeviceConfigController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using NewLife.Cube; 5 | using NewLife.Web; 6 | using xLink.Entity; 7 | 8 | namespace xLink.Web.Areas.Devices.Controllers 9 | { 10 | [DevicesArea] 11 | [DisplayName("设备配置")] 12 | public class DeviceConfigController : EntityController 13 | { 14 | static DeviceConfigController() => MenuOrder = 40; 15 | 16 | protected override IEnumerable Search(Pager p) 17 | { 18 | var cityId = p["cityId"].ToInt(-1); 19 | var deviceId = p["deviceId"].ToInt(-1); 20 | var name = p["name"]; 21 | 22 | var start = p["dtStart"].ToDateTime(); 23 | var end = p["dtEnd"].ToDateTime(); 24 | 25 | return DeviceConfig.Search(cityId, deviceId, name, start, end, p["Q"], p); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/DeviceController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using Microsoft.AspNetCore.Mvc; 6 | using NewLife; 7 | using NewLife.Cube; 8 | using NewLife.Web; 9 | using xLink.Entity; 10 | 11 | namespace xLink.Web.Areas.Devices.Controllers 12 | { 13 | [DevicesArea] 14 | [DisplayName("设备")] 15 | public class DeviceController : EntityController 16 | { 17 | static DeviceController() => MenuOrder = 80; 18 | 19 | protected override IEnumerable Search(Pager p) 20 | { 21 | var deviceId = p["Id"].ToInt(-1); 22 | if (deviceId > 0) 23 | { 24 | var dv = Device.FindByID(deviceId); 25 | if (dv != null) return new[] { dv }; 26 | } 27 | 28 | var productId = p["productId"].ToInt(-1); 29 | var rids = p["areaId"].SplitAsInt("/"); 30 | var provinceId = rids.Length > 0 ? rids[0] : -1; 31 | var cityId = rids.Length > 1 ? rids[1] : -1; 32 | 33 | var version = p["version"]; 34 | var enable = p["enable"]?.ToBoolean(); 35 | 36 | var start = p["dtStart"].ToDateTime(); 37 | var end = p["dtEnd"].ToDateTime(); 38 | 39 | return Device.Search(productId, provinceId, cityId, version, enable, start, end, p["Q"], p); 40 | } 41 | 42 | public ActionResult Trace(Int32 id) 43 | { 44 | var dv = Device.FindByID(id); 45 | if (dv != null) 46 | { 47 | DeviceCommand.Add(dv, "截屏"); 48 | DeviceCommand.Add(dv, "抓日志"); 49 | } 50 | 51 | // 跳转到来源页 52 | var url = Request.Headers["Referer"].FirstOrDefault() + ""; 53 | if (url != null) return Redirect(url); 54 | 55 | return RedirectToAction("Index"); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/DeviceHistoryController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using NewLife; 5 | using NewLife.Cube; 6 | using NewLife.Web; 7 | using xLink.Entity; 8 | 9 | namespace xLink.Web.Areas.Devices.Controllers 10 | { 11 | [DevicesArea] 12 | [DisplayName("设备历史")] 13 | public class DeviceHistoryController : EntityController 14 | { 15 | static DeviceHistoryController() => MenuOrder = 60; 16 | 17 | protected override IEnumerable Search(Pager p) 18 | { 19 | var rids = p["areaId"].SplitAsInt("/"); 20 | var cityId = rids.Length > 1 ? rids[1] : -1; 21 | 22 | var deviceId = p["deviceId"].ToInt(-1); 23 | var action = p["action"]; 24 | //var success = p["success"]?.ToBoolean(); 25 | Boolean? success = null; 26 | if (!p["success"].IsNullOrEmpty()) success = p["success"].ToBoolean(); 27 | 28 | var start = p["dtStart"].ToDateTime(); 29 | var end = p["dtEnd"].ToDateTime(); 30 | 31 | return DeviceHistory.Search(cityId, deviceId, action, success, start, end, p["Q"], p); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/DeviceOnlineController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using Microsoft.AspNetCore.Mvc; 5 | using NewLife; 6 | using NewLife.Cube; 7 | using NewLife.Web; 8 | using XCode.Membership; 9 | using xLink.Entity; 10 | 11 | namespace xLink.Web.Areas.Devices.Controllers 12 | { 13 | [DevicesArea] 14 | [DisplayName("设备在线")] 15 | public class DeviceOnlineController : EntityController 16 | { 17 | static DeviceOnlineController() => MenuOrder = 70; 18 | 19 | protected override IEnumerable Search(Pager p) 20 | { 21 | var productId = p["productId"].ToInt(-1); 22 | var deviceId = p["deviceId"].ToInt(-1); 23 | var rids = p["areaId"].SplitAsInt("/"); 24 | var cityId = rids.Length > 1 ? rids[1] : -1; 25 | 26 | var start = p["dtStart"].ToDateTime(); 27 | var end = p["dtEnd"].ToDateTime(); 28 | 29 | return DeviceOnline.Search(productId, deviceId, cityId, start, end, p["Q"], p); 30 | } 31 | 32 | /// 批量跟踪 33 | /// 34 | [EntityAuthorize(PermissionFlags.Update)] 35 | public ActionResult Trace() 36 | { 37 | var ids = GetRequest("keys").SplitAsInt(); 38 | foreach (var item in ids) 39 | { 40 | var dv = DeviceOnline.FindByID(item)?.Device; 41 | if (dv != null) 42 | { 43 | DeviceCommand.Add(dv, "截屏"); 44 | DeviceCommand.Add(dv, "抓日志"); 45 | } 46 | } 47 | 48 | return JsonRefresh("操作成功!"); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/ProductController.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using NewLife.Cube; 3 | using xLink.Entity; 4 | 5 | namespace xLink.Web.Areas.Devices.Controllers 6 | { 7 | [DevicesArea] 8 | [DisplayName("产品")] 9 | public class ProductController : EntityController 10 | { 11 | static ProductController() => MenuOrder = 90; 12 | } 13 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/ProductVersionController.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using NewLife.Cube; 3 | using xLink.Entity; 4 | 5 | namespace xLink.Web.Areas.Devices.Controllers 6 | { 7 | [DevicesArea] 8 | [DisplayName("产品版本")] 9 | public class ProductVersionController : EntityController 10 | { 11 | static ProductVersionController() => MenuOrder = 89; 12 | } 13 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Controllers/SubDeviceController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using NewLife.Cube; 5 | using NewLife.Web; 6 | using xLink.Entity; 7 | 8 | namespace xLink.Web.Areas.Devices.Controllers 9 | { 10 | [DevicesArea] 11 | [DisplayName("子设备")] 12 | public class SubDeviceController : EntityController 13 | { 14 | static SubDeviceController() => MenuOrder = 58; 15 | 16 | protected override IEnumerable Search(Pager p) 17 | { 18 | var deviceId = p["deviceId"].ToInt(-1); 19 | var productId = p["productId"].ToInt(-1); 20 | 21 | var enable = p["enable"]?.ToBoolean(); 22 | 23 | var start = p["dtStart"].ToDateTime(); 24 | var end = p["dtEnd"].ToDateTime(); 25 | 26 | return SubDevice.Search(deviceId, productId, enable, start, end, p["Q"], p); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/DevicesArea.cs: -------------------------------------------------------------------------------- 1 | using NewLife; 2 | using NewLife.Cube; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace xLink.Web.Areas.Devices 10 | { 11 | [DisplayName("设备管理")] 12 | public class DevicesArea : AreaBase 13 | { 14 | public DevicesArea() : base(nameof(DevicesArea).TrimEnd("Area")) { } 15 | 16 | static DevicesArea() => RegisterArea(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/Device/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using NewLife.Cube; 4 | @using XCode; 5 | @using xLink.Entity; 6 | @{ 7 | var fact = ViewBag.Factory as IEntityFactory; 8 | var page = ViewBag.Page as Pager; 9 | } 10 | @await Html.PartialAsync("_Area2", "") 11 |
12 | 13 | @Html.ForDropDownList("productId", Product.FindAllWithCache(), page["productId"], "全部", true) 14 |
15 |
16 | 17 | @Html.ForDropDownList("version", Device.FindAllVersion(), page["version"], "全部", true) 18 |
19 | @await Html.PartialAsync("_DateRange") -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceCommand/_List_Data.cshtml: -------------------------------------------------------------------------------- 1 | @model IList 2 | @using xLink.Entity 3 | @using NewLife; 4 | @using NewLife.Web; 5 | @using XCode; 6 | @using XCode.Configuration; 7 | @using XCode.Membership; 8 | @using NewLife.Cube; 9 | @{ 10 | var fact = ViewBag.Factory as IEntityFactory; 11 | var page = ViewBag.Page as Pager; 12 | var fields = ViewBag.Fields as IList; 13 | var set = ViewBag.PageSetting as PageSetting; 14 | var provider = ManageProvider.Provider; 15 | } 16 | 17 | 18 | 19 | @if (set.EnableSelect) 20 | { 21 | 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | @if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete)) 35 | { 36 | 37 | } 38 | 39 | 40 | 41 | @foreach (var entity in Model) 42 | { 43 | var baseUrl = Parameter.GetOrAdd(0, "Node", "BaseUrl-" + entity.CreateUser, "http://localhost:5000"); 44 | var url = $"{baseUrl.GetValue()}/device/getresult?id={entity.ID}&deviceId={entity.DeviceId}"; 45 | 46 | @if (set.EnableSelect) 47 | { 48 | 49 | } 50 | 51 | 52 | 53 | 54 | 55 | 58 | 59 | 60 | 61 | 62 | 63 | @if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete)) 64 | { 65 | 68 | } 69 | 70 | } 71 | 72 |
编号设备地区命令参数完成结果创建节点创建者创建时间更新时间操作
@entity.ID@entity.DeviceName@entity.CityName@entity.Command@entity.Argument 56 | 57 | @entity.Result@entity.CreateUser@provider.FindByID(entity.CreateUserID)@entity.CreateTime.ToFullString("")@entity.UpdateTime.ToFullString("") 66 | @await Html.PartialAsync("_List_Data_Action", (Object)entity) 67 |
-------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceConfig/_List_Data.cshtml: -------------------------------------------------------------------------------- 1 | @model IList 2 | @using xLink.Entity 3 | @using NewLife; 4 | @using NewLife.Web; 5 | @using XCode; 6 | @using XCode.Configuration; 7 | @using XCode.Membership; 8 | @using NewLife.Cube; 9 | @{ 10 | var fact = ViewBag.Factory as IEntityFactory; 11 | var page = ViewBag.Page as Pager; 12 | var fields = ViewBag.Fields as IList; 13 | var set = ViewBag.PageSetting as PageSetting; 14 | var provider = ManageProvider.Provider; 15 | } 16 | 17 | 18 | 19 | @if (set.EnableSelect) 20 | { 21 | 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete)) 31 | { 32 | 33 | } 34 | 35 | 36 | 37 | @foreach (var entity in Model) 38 | { 39 | 40 | @if (set.EnableSelect) 41 | { 42 | 43 | } 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | @if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete)) 52 | { 53 | 56 | } 57 | 58 | } 59 | 60 |
编号设备地区名称内容更新时间更新地址操作
@entity.ID@entity.DeviceName@entity.City@entity.Name@entity.Content@entity.UpdateTime.ToFullString("")@entity.UpdateIP 54 | @await Html.PartialAsync("_List_Data_Action", (Object)entity) 55 |
-------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceConfig/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using NewLife.Cube; 4 | @using XCode; 5 | @using xLink.Entity; 6 | @{ 7 | var fact = ViewBag.Factory as IEntityFactory; 8 | var page = ViewBag.Page as Pager; 9 | } 10 |
11 | 12 | @Html.ForDropDownList("name", DeviceConfig.FindAllName(), page["name"], "全部", true) 13 |
-------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceHistory/_List_Data.cshtml: -------------------------------------------------------------------------------- 1 | @model IList 2 | @using xLink.Entity 3 | @using NewLife; 4 | @using NewLife.Web; 5 | @using XCode; 6 | @using XCode.Configuration; 7 | @using XCode.Membership; 8 | @using NewLife.Cube; 9 | @{ 10 | var fact = ViewBag.Factory as IEntityFactory; 11 | var page = ViewBag.Page as Pager; 12 | var fields = ViewBag.Fields as IList; 13 | var set = ViewBag.PageSetting as PageSetting; 14 | //var provider = ManageProvider.Provider; 15 | } 16 | 17 | 18 | 19 | @if (set.EnableSelect) 20 | { 21 | 22 | } 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | @if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete)) 33 | { 34 | 35 | } 36 | 37 | 38 | 39 | @foreach (var entity in Model) 40 | { 41 | var ctime = entity.CreateTime; 42 | var createTime = ctime.Date == DateTime.Today ? ctime.ToString("HH:mm:ss") : ctime.ToFullString(); 43 | 44 | @if (set.EnableSelect) 45 | { 46 | 47 | } 48 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 | 59 | @if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete)) 60 | { 61 | 64 | } 65 | 66 | } 67 | 68 |
编号地区设备操作成功创建时间内容创建者创建地址操作
@entity.ID@entity.CityName@entity.Name@entity.Action 53 | 54 | @createTime@entity.Remark@entity.Creator@entity.CreateIP 62 | @await Html.PartialAsync("_List_Data_Action", (Object)entity) 63 |
-------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceHistory/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife; 2 | @using NewLife.Web; 3 | @using NewLife.Cube; 4 | @using XCode; 5 | @using xLink.Entity; 6 | @{ 7 | var fact = ViewBag.Factory as IEntityFactory; 8 | var page = ViewBag.Page as Pager; 9 | 10 | var dic = new Dictionary(); 11 | dic.Add(1, "成功"); 12 | dic.Add(0, "失败"); 13 | } 14 |
15 | 16 | @Html.ForDropDownList("action", DeviceHistory.FindAllAction(), page["action"], "全部", true) 17 |
18 |
19 | 20 | @Html.ForDropDownList("success", dic, page["success"], "全部", true) 21 |
22 | @await Html.PartialAsync("_DateRange") -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceOnline/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using xLink.Entity 2 | @using NewLife; 3 | @using NewLife.Web; 4 | @using XCode; 5 | @{ 6 | var fact = ViewBag.Factory as IEntityFactory; 7 | var page = ViewBag.Page as Pager; 8 | } 9 | @await Html.PartialAsync("_Area2", "") 10 |
11 | 12 | @Html.ForDropDownList("productId", Product.FindAllWithCache(), page["productId"], "全部", true) 13 |
-------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceOnline/_List_Toolbar_Batch.cshtml: -------------------------------------------------------------------------------- 1 | @using NewLife.Common; 2 | @using System.Collections.Generic; 3 | @{ 4 | var user = ViewBag.User as IUser ?? User.Identity as IUser; 5 | var fact = ViewBag.Factory as IEntityFactory; 6 | var set = ViewBag.PageSetting as PageSetting; 7 | 8 | var sdic = new Dictionary(); 9 | sdic["strFormat"] = "yyyy-MM-dd HH:mm:ss"; 10 | sdic["dname"] = "sday"; 11 | sdic["title"] = "开始"; 12 | 13 | var edic = new Dictionary(); 14 | edic["strFormat"] = "yyyy-MM-dd HH:mm:ss"; 15 | edic["dname"] = "eday"; 16 | edic["title"] = "结束"; 17 | } 18 | @if (set.EnableSelect) 19 | { 20 | 23 | } -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/DeviceStat/_List_Search.cshtml: -------------------------------------------------------------------------------- 1 | @using xLink.Entity 2 | @using NewLife; 3 | @using NewLife.Web; 4 | @using XCode; 5 | @{ 6 | var fact = ViewBag.Factory as IEntityFactory; 7 | var page = ViewBag.Page as Pager; 8 | } 9 |
10 | 11 | @Html.ForDropDownList("productId", Product.FindAllWithCache(), page["productId"], "全部", true) 12 |
13 | @await Html.PartialAsync("_DateRange") -------------------------------------------------------------------------------- /xLink.Web/Areas/Devices/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 2 | @using NewLife 3 | @using NewLife.Cube 4 | @using NewLife.Reflection 5 | @using NewLife.Web 6 | @using XCode 7 | @using XCode.Membership 8 | -------------------------------------------------------------------------------- /xLink.Web/Entity/Build.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/xLink.Web/Entity/Build.cs -------------------------------------------------------------------------------- /xLink.Web/Entity/Build.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" hostSpecific="true" debug="true" #> 2 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\NewLife.Core.dll" #> 3 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\XCode.dll" #> 4 | <#@ import namespace="System.Diagnostics" #> 5 | <#@ import namespace="System.IO" #> 6 | <#@ import namespace="XCode.Code" #> 7 | <#@ output extension=".log" #> 8 | <# 9 | // 设置当前工作目录 10 | PathHelper.BasePath = Host.ResolvePath("."); 11 | 12 | // 加载模型文件,得到数据表 13 | var option = new BuilderOption(); 14 | var tables = ClassBuilder.LoadModels(null, option, out var atts); 15 | EntityBuilder.FixModelFile(null, option, atts, tables); 16 | 17 | // 生成实体类 18 | //option.BaseClass = "I{name}"; 19 | //option.ModelNameForCopy = "I{name}"; 20 | EntityBuilder.BuildTables(tables, option, chineseFileName: true); 21 | 22 | // 生成简易模型类 23 | option.Output = @"Output\EntityModels\"; 24 | option.ClassNameTemplate = "{name}Model"; 25 | option.ModelNameForCopy = "I{name}"; 26 | //ClassBuilder.BuildModels(tables, option); 27 | 28 | // 生成简易接口 29 | option.BaseClass = null; 30 | option.ClassNameTemplate = null; 31 | option.Output = @"Output\EntityInterfaces\"; 32 | //ClassBuilder.BuildInterfaces(tables, option); 33 | 34 | // 精确控制生成 35 | /*foreach (var item in tables) 36 | { 37 | var builder = new ClassBuilder 38 | { 39 | Table = item, 40 | Option = option.Clone(), 41 | }; 42 | builder.Execute(); 43 | builder.Save(null, true, false); 44 | }*/ 45 | #> -------------------------------------------------------------------------------- /xLink.Web/Entity/Build_netcore.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NewLifeX/XLink/9746943970069421d771d9fd356b03fd58710026/xLink.Web/Entity/Build_netcore.cs -------------------------------------------------------------------------------- /xLink.Web/Entity/Build_netcore.tt: -------------------------------------------------------------------------------- 1 | <#@ template language="C#" hostSpecific="true" debug="true" #> 2 | <#@ assembly name="netstandard" #> 3 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\NewLife.Core.dll" #> 4 | <#@ assembly name="$(ProjectDir)\$(OutputPath)\XCode.dll" #> 5 | <#@ import namespace="System.Diagnostics" #> 6 | <#@ import namespace="System.IO" #> 7 | <#@ import namespace="XCode.Code" #> 8 | <#@ output extension=".log" #> 9 | <# 10 | // 设置当前工作目录 11 | PathHelper.BasePath = Host.ResolvePath("."); 12 | 13 | // 加载模型文件,得到数据表 14 | var option = new BuilderOption(); 15 | var tables = ClassBuilder.LoadModels(null, option, out var atts); 16 | EntityBuilder.FixModelFile(null, option, atts, tables); 17 | 18 | // 生成实体类 19 | //option.BaseClass = "I{name}"; 20 | //option.ModelNameForCopy = "I{name}"; 21 | EntityBuilder.BuildTables(tables, option, chineseFileName: true); 22 | 23 | // 生成简易模型类 24 | option.Output = @"Output\EntityModels\"; 25 | option.ClassNameTemplate = "{name}Model"; 26 | option.ModelNameForCopy = "I{name}"; 27 | //ClassBuilder.BuildModels(tables, option); 28 | 29 | // 生成简易接口 30 | option.BaseClass = null; 31 | option.ClassNameTemplate = null; 32 | option.Output = @"Output\EntityInterfaces\"; 33 | //ClassBuilder.BuildInterfaces(tables, option); 34 | 35 | // 精确控制生成 36 | /*foreach (var item in tables) 37 | { 38 | var builder = new ClassBuilder 39 | { 40 | Table = item, 41 | Option = option.Clone(), 42 | }; 43 | builder.Execute(); 44 | builder.Save(null, true, false); 45 | }*/ 46 | #> -------------------------------------------------------------------------------- /xLink.Web/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using NewLife.Log; 5 | 6 | namespace xLink.Web 7 | { 8 | public class Program 9 | { 10 | public static void Main(String[] args) 11 | { 12 | XTrace.UseConsole(); 13 | 14 | CreateHostBuilder(args).Build().Run(); 15 | } 16 | 17 | public static IHostBuilder CreateHostBuilder(String[] args) 18 | { 19 | return Host.CreateDefaultBuilder(args) 20 | //.ConfigureLogging(logging => { logging.AddXLog(); }) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /xLink.Web/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:51049/", 7 | "sslPort": 44359 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "xLink.Web": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /xLink.Web/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using NewLife.Cube; 7 | 8 | namespace xLink.Web 9 | { 10 | public class Startup 11 | { 12 | /// 13 | /// 14 | public Startup(IConfiguration configuration) { } 15 | 16 | /// 17 | /// 18 | public void ConfigureServices(IServiceCollection services) => services.AddCube(); 19 | 20 | /// 21 | /// 22 | /// 23 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 24 | { 25 | // 使用Cube前添加自己的管道 26 | if (env.IsDevelopment()) 27 | app.UseDeveloperExceptionPage(); 28 | else 29 | app.UseExceptionHandler("/CubeHome/Error"); 30 | 31 | app.UseStaticFiles(new StaticFileOptions { ServeUnknownFileTypes = true }); 32 | 33 | app.UseCube(env); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /xLink.Web/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Warning" 5 | } 6 | }, 7 | "Port": 8080, 8 | "AllowedHosts": "*", 9 | "ConnectionStrings": { 10 | "xLink": { 11 | "connectionString": "Data Source=..\\Data\\xLink.db", 12 | "providerName": "SQLite" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /xLink.Web/xLink.Web.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | xLinkWeb 6 | 物联网平台 7 | 扫描系统管理平台 8 | 新生命开发团队 9 | 版权所有(C) 新生命开发团队 2002~2025 10 | 3.1.2020.0708 11 | 3.1.2020.0708 12 | 3.1.* 13 | false 14 | ..\Bin\Web 15 | false 16 | pdbonly 17 | true 18 | TRACE 19 | latest 20 | 21 | 22 | 23 | $(DefineConstants);DEBUG 24 | full 25 | false 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /xLink.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30225.117 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xLink", "xLink\xLink.csproj", "{8DF06706-AD6E-4F75-99A8-3F610F0FBE7C}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xLink.Server", "xLink.Server\xLink.Server.csproj", "{F51C838F-757F-415B-8968-94E3C9029D82}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Other", "Other", "{E9E982D4-367F-4305-ABDF-3B590673DADD}" 11 | ProjectSection(SolutionItems) = preProject 12 | Readme.MD = Readme.MD 13 | EndProjectSection 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xLink.Client", "xLink.Client\xLink.Client.csproj", "{9B82E70B-389D-4328-A5E2-BE2837072C38}" 16 | EndProject 17 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xLink.Web", "xLink.Web\xLink.Web.csproj", "{779BC3B7-BA72-4049-837D-3DDC53FBC0A9}" 18 | EndProject 19 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{9230D351-C064-4B0D-B86D-4C76E85762E5}" 20 | ProjectSection(SolutionItems) = preProject 21 | .editorconfig = .editorconfig 22 | EndProjectSection 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xLink.Data", "xLink.Data\xLink.Data.csproj", "{3A0A4E07-B5BC-4307-B6CB-8E57F1E9AACC}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "xLink.HttpServer", "xLink.HttpServer\xLink.HttpServer.csproj", "{8A14F8E7-BF9C-4294-B307-F6F927CCBC1D}" 27 | EndProject 28 | Global 29 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 30 | Debug|Any CPU = Debug|Any CPU 31 | Release|Any CPU = Release|Any CPU 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {8DF06706-AD6E-4F75-99A8-3F610F0FBE7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {8DF06706-AD6E-4F75-99A8-3F610F0FBE7C}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {8DF06706-AD6E-4F75-99A8-3F610F0FBE7C}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {8DF06706-AD6E-4F75-99A8-3F610F0FBE7C}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {F51C838F-757F-415B-8968-94E3C9029D82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {F51C838F-757F-415B-8968-94E3C9029D82}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {F51C838F-757F-415B-8968-94E3C9029D82}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {F51C838F-757F-415B-8968-94E3C9029D82}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {9B82E70B-389D-4328-A5E2-BE2837072C38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {9B82E70B-389D-4328-A5E2-BE2837072C38}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {9B82E70B-389D-4328-A5E2-BE2837072C38}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {9B82E70B-389D-4328-A5E2-BE2837072C38}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {779BC3B7-BA72-4049-837D-3DDC53FBC0A9}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {3A0A4E07-B5BC-4307-B6CB-8E57F1E9AACC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {3A0A4E07-B5BC-4307-B6CB-8E57F1E9AACC}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {3A0A4E07-B5BC-4307-B6CB-8E57F1E9AACC}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {3A0A4E07-B5BC-4307-B6CB-8E57F1E9AACC}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {8A14F8E7-BF9C-4294-B307-F6F927CCBC1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {8A14F8E7-BF9C-4294-B307-F6F927CCBC1D}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {8A14F8E7-BF9C-4294-B307-F6F927CCBC1D}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {8A14F8E7-BF9C-4294-B307-F6F927CCBC1D}.Release|Any CPU.Build.0 = Release|Any CPU 58 | EndGlobalSection 59 | GlobalSection(SolutionProperties) = preSolution 60 | HideSolutionNode = FALSE 61 | EndGlobalSection 62 | GlobalSection(ExtensibilityGlobals) = postSolution 63 | SolutionGuid = {E2BACAC2-15CC-4C71-9436-1616D7607684} 64 | EndGlobalSection 65 | EndGlobal 66 | -------------------------------------------------------------------------------- /xLink/Common/MachineHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.NetworkInformation; 6 | using System.Net.Sockets; 7 | 8 | namespace xLink.Common 9 | { 10 | /// 机器信息助手 11 | public class MachineHelper 12 | { 13 | private static String[] _Excludes = new[] { "Loopback", "VMware", "VBox", "Virtual", "Teredo", "Microsoft", "VPN", "VNIC", "IEEE" }; 14 | private static NetworkInterface[] _ifs; 15 | /// 获取所有网卡MAC地址 16 | /// 17 | public static IEnumerable GetMacs() 18 | { 19 | if (_ifs == null) _ifs = NetworkInterface.GetAllNetworkInterfaces(); 20 | 21 | foreach (var item in _ifs) 22 | { 23 | if (_Excludes.Any(e => item.Description.Contains(e))) continue; 24 | if (item.Speed < 1_000_000) continue; 25 | 26 | var ips = item.GetIPProperties(); 27 | var addrs = ips.UnicastAddresses 28 | .Where(e => e.Address.AddressFamily == AddressFamily.InterNetwork) 29 | .Select(e => e.Address) 30 | .ToArray(); 31 | if (addrs.All(e => IPAddress.IsLoopback(e))) continue; 32 | 33 | var mac = item.GetPhysicalAddress()?.GetAddressBytes(); 34 | if (mac != null && mac.Length == 6) yield return mac; 35 | } 36 | } 37 | 38 | /// 获取网卡MAC地址(网关所在网卡) 39 | /// 40 | public static Byte[] GetMac() 41 | { 42 | if (_ifs == null) _ifs = NetworkInterface.GetAllNetworkInterfaces(); 43 | 44 | foreach (var item in _ifs) 45 | { 46 | if (_Excludes.Any(e => item.Description.Contains(e))) continue; 47 | if (item.Speed < 1_000_000) continue; 48 | 49 | var ips = item.GetIPProperties(); 50 | var addrs = ips.UnicastAddresses 51 | .Where(e => e.Address.AddressFamily == AddressFamily.InterNetwork) 52 | .Select(e => e.Address) 53 | .ToArray(); 54 | if (addrs.All(e => IPAddress.IsLoopback(e))) continue; 55 | 56 | // 网关 57 | addrs = ips.GatewayAddresses 58 | .Where(e => e.Address.AddressFamily == AddressFamily.InterNetwork) 59 | .Select(e => e.Address) 60 | .ToArray(); 61 | if (addrs.Length == 0) continue; 62 | 63 | var mac = item.GetPhysicalAddress()?.GetAddressBytes(); 64 | if (mac != null && mac.Length == 6) return mac; 65 | } 66 | 67 | return null; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /xLink/Models/DataModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 数据模型 6 | public class DataModel 7 | { 8 | /// 设备 9 | public String ID { get; set; } 10 | 11 | /// 起始位置 12 | public Int32 Start { get; set; } 13 | 14 | /// 数据 15 | public String Data { get; set; } 16 | } 17 | } -------------------------------------------------------------------------------- /xLink/Models/DeviceInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 设备信息 6 | public class DeviceInfo 7 | { 8 | #region 属性 9 | /// 版本 10 | public String Version { get; set; } 11 | 12 | /// 编译时间 13 | public DateTime Compile { get; set; } 14 | 15 | /// 系统名 16 | public String OSName { get; set; } 17 | 18 | /// 系统版本 19 | public String OSVersion { get; set; } 20 | 21 | /// 机器名 22 | public String MachineName { get; set; } 23 | 24 | /// 用户名 25 | public String UserName { get; set; } 26 | 27 | /// 核心数 28 | public Int32 ProcessorCount { get; set; } 29 | 30 | /// 内存大小 31 | public UInt64 Memory { get; set; } 32 | 33 | /// 可用内存大小 34 | public UInt64 AvailableMemory { get; set; } 35 | 36 | /// 磁盘大小。应用所在盘 37 | public UInt64 TotalSize { get; set; } 38 | 39 | /// 磁盘可用空间。应用所在盘 40 | public UInt64 AvailableFreeSpace { get; set; } 41 | 42 | /// 像素点。默认96*96 43 | public String Dpi { get; set; } 44 | 45 | /// 分辨率。例如1024*768 46 | public String Resolution { get; set; } 47 | 48 | /// 处理器 49 | public String Processor { get; set; } 50 | 51 | /// 处理器标识 52 | public String CpuID { get; set; } 53 | 54 | /// 主频 55 | public Single CpuRate { get; set; } 56 | 57 | /// 唯一标识 58 | public String UUID { get; set; } 59 | 60 | /// 机器标识 61 | public String MachineGuid { get; set; } 62 | 63 | /// 磁盘标识 64 | public String DiskID { get; set; } 65 | 66 | /// MAC地址 67 | public String Macs { get; set; } 68 | 69 | /// 串口 70 | public String COMs { get; set; } 71 | 72 | /// 安装路径 73 | public String InstallPath { get; set; } 74 | 75 | /// 运行时 76 | public String Runtime { get; set; } 77 | 78 | /// 本地UTC时间 79 | /// 80 | /// 跨系统传递UTC时间是严谨的,但是UTC时间序列化比较头疼,目前能够做到自己序列化后,自己能够解析出来,暂时用着,将来向netcore的system.text.json序列化迁移 81 | /// 82 | public DateTime Time { get; set; } 83 | #endregion 84 | } 85 | } -------------------------------------------------------------------------------- /xLink/Models/IHistory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 历史接口,用户操作历史 6 | public interface IHistory 7 | { 8 | #region 属性 9 | /// 会员 10 | Int32 UserID { get; set; } 11 | 12 | /// 名称 13 | String Name { get; set; } 14 | 15 | ///// 类型 16 | //String Type { get; set; } 17 | 18 | /// 操作 19 | String Action { get; set; } 20 | 21 | /// 成功 22 | Boolean Success { get; set; } 23 | 24 | ///// 创建者 25 | //Int32 CreateUserID { get; set; } 26 | 27 | /// 创建时间 28 | DateTime CreateTime { get; set; } 29 | 30 | /// 创建地址 31 | String CreateIP { get; set; } 32 | 33 | /// 内容 34 | String Remark { get; set; } 35 | #endregion 36 | 37 | /// 异步保存。实现延迟保存,大事务保存。主要面向日志表和频繁更新的在线记录表 38 | /// 延迟保存的时间。默认0ms近实时保存 39 | /// 是否成功加入异步队列 40 | Boolean SaveAsync(Int32 msDelay = 0); 41 | } 42 | } -------------------------------------------------------------------------------- /xLink/Models/IOnline.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 在线接口,用户在线离线 6 | public interface IOnline 7 | { 8 | #region 属性 9 | /// 会员 10 | Int32 UserID { get; set; } 11 | 12 | /// 名称 13 | String Name { get; set; } 14 | 15 | ///// 类型 16 | //String Type { get; set; } 17 | 18 | /// 会话 19 | String SessionID { get; set; } 20 | 21 | /// 创建时间 22 | DateTime CreateTime { get; set; } 23 | 24 | /// 创建地址 25 | String CreateIP { get; set; } 26 | 27 | /// 更新时间 28 | DateTime UpdateTime { get; set; } 29 | #endregion 30 | 31 | /// 异步保存。实现延迟保存,大事务保存。主要面向日志表和频繁更新的在线记录表 32 | /// 延迟保存的时间。默认0ms近实时保存 33 | /// 是否成功加入异步队列 34 | Boolean SaveAsync(Int32 msDelay = 0); 35 | 36 | /// 从数据库中删除该对象 37 | /// 38 | Int32 Delete(); 39 | 40 | /// 保存 41 | /// 42 | Int32 Save(); 43 | } 44 | } -------------------------------------------------------------------------------- /xLink/Models/LoginInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 设备登录信息 6 | public class LoginInfo 7 | { 8 | #region 属性 9 | /// 设备编码 10 | public String Code { get; set; } 11 | 12 | /// 设备密钥 13 | public String Secret { get; set; } 14 | 15 | /// 设备信息 16 | public DeviceInfo Device { get; set; } 17 | #endregion 18 | } 19 | 20 | /// 设备登录响应 21 | public class LoginResponse 22 | { 23 | #region 属性 24 | /// 设备编码 25 | public String Code { get; set; } 26 | 27 | /// 设备密钥 28 | public String Secret { get; set; } 29 | 30 | /// 名称 31 | public String Name { get; set; } 32 | 33 | /// 令牌 34 | public String Token { get; set; } 35 | 36 | /// 服务端版本 37 | public String Version { get; set; } 38 | #endregion 39 | } 40 | } -------------------------------------------------------------------------------- /xLink/Models/PingInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 心跳信息 6 | public class PingInfo 7 | { 8 | #region 属性 9 | /// 可用内存大小 10 | public UInt64 AvailableMemory { get; set; } 11 | 12 | /// 磁盘可用空间。应用所在盘 13 | public UInt64 AvailableSpace { get; set; } 14 | 15 | /// 主频 16 | public Single CpuRate { get; set; } 17 | 18 | /// 温度 19 | public Double Temperature { get; set; } 20 | 21 | /// MAC地址 22 | public String Macs { get; set; } 23 | 24 | /// 串口 25 | public String COMs { get; set; } 26 | 27 | /// 进程列表 28 | public String Processes { get; set; } 29 | 30 | /// 开机时间,ms 31 | public Int32 Uptime { get; set; } 32 | 33 | /// 本地UTC时间。ms毫秒 34 | public Int64 Time { get; set; } 35 | 36 | /// 延迟 37 | public Int32 Delay { get; set; } 38 | #endregion 39 | } 40 | 41 | /// 心跳响应 42 | public class PingResponse 43 | { 44 | /// 本地时间。ms毫秒 45 | public Int64 Time { get; set; } 46 | 47 | /// 服务器时间 48 | public DateTime ServerTime { get; set; } 49 | 50 | /// 下发命令 51 | public CommandModel[] Commands { get; set; } 52 | } 53 | 54 | /// 命令模型 55 | public class CommandModel 56 | { 57 | /// 序号 58 | public Int32 Id { get; set; } 59 | 60 | /// 命令 61 | public String Command { get; set; } 62 | 63 | /// 参数 64 | public String Argument { get; set; } 65 | 66 | //public String Result { get; set; } 67 | } 68 | } -------------------------------------------------------------------------------- /xLink/Models/ServiceInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace xLink.Models 5 | { 6 | /// 服务信息 7 | public class ServiceInfo 8 | { 9 | #region 属性 10 | /// 名称 11 | [XmlAttribute] 12 | public String Name { get; set; } 13 | 14 | /// 文件 15 | [XmlAttribute] 16 | public String FileName { get; set; } 17 | 18 | /// 参数 19 | [XmlAttribute] 20 | public String Arguments { get; set; } 21 | 22 | ///// 工作目录 23 | //[XmlAttribute] 24 | //public String WorkingDirectory { get; set; } 25 | 26 | /// 是否自动启动 27 | [XmlAttribute] 28 | public Boolean AutoStart { get; set; } 29 | 30 | /// 启动失败时的重试次数,默认3次 31 | [XmlAttribute] 32 | public Int32 Retry { get; set; } = 3; 33 | 34 | /// 是否自动重启。应用进程退出后,自动拉起,默认true 35 | [XmlAttribute] 36 | public Boolean AutoRestart { get; set; } = true; 37 | 38 | ///// 重启退出代码。仅有该退出代码才会重启 39 | //[XmlAttribute] 40 | //public String RestartExistCodes { get; set; } 41 | #endregion 42 | } 43 | } -------------------------------------------------------------------------------- /xLink/Models/UpgradeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace xLink.Models 4 | { 5 | /// 更新响应 6 | public class UpgradeInfo 7 | { 8 | /// 版本号 9 | public String Version { get; set; } 10 | 11 | /// 更新源,Url地址 12 | public String Source { get; set; } 13 | 14 | /// 更新后要执行的命令 15 | public String Executor { get; set; } 16 | 17 | /// 是否强制更新,不需要用户同意 18 | public Boolean Force { get; set; } 19 | 20 | /// 描述 21 | public String Description { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /xLink/xLink.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net45;netstandard2.0;net40 4 | xLink 5 | xLink 6 | 菲凡物联 7 | 物联网通信协议 8 | 新生命开发团队 9 | 版权所有(C) 新生命开发团队 2002~2025 10 | 3.1.2020.0708 11 | 3.1.2020.0708 12 | 3.1.* 13 | false 14 | ..\Bin 15 | $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml 16 | pdbonly 17 | true 18 | TRACE 19 | 20 | 21 | 22 | NewLife.$(AssemblyName) 23 | $(Company) 24 | https://github.com/NewLifeX 25 | http://www.NewLifeX.com/favicon.ico 26 | https://github.com/NewLifeX/xLink 27 | git 28 | 新生命团队;X组件;NewLife;$(AssemblyName) 29 | 支持NET40 30 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 31 | true 32 | true 33 | true 34 | latest 35 | 36 | 37 | 38 | $(DefineConstants);NETSTANDARD2_0;__CORE__ 39 | 40 | 41 | 42 | $(DefineConstants);__WIN__ 43 | 44 | 45 | 46 | $(DefineConstants);__WIN__;NET4 47 | 48 | 49 | 50 | $(DefineConstants);DEBUG 51 | full 52 | false 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | True 78 | True 79 | XCoder.tt 80 | 81 | 82 | TextTemplatingFileGenerator 83 | XCoder.log 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | --------------------------------------------------------------------------------