diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/SensorHub.Servers/CasicReceiveFilter.cs b/SensorHub.Servers/CasicReceiveFilter.cs index 6b270ce..43c1bfd 100644 --- a/SensorHub.Servers/CasicReceiveFilter.cs +++ b/SensorHub.Servers/CasicReceiveFilter.cs @@ -6,6 +6,8 @@ using SuperSocket.SocketBase.Protocol; using SuperSocket.Common; using SensorHub.Utility; +using SensorHub.Servers.SM4; + namespace SensorHub.Servers { @@ -20,8 +22,9 @@ protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { int tagLength = (int)header[offset + 2] * 256 + (int)header[offset + 3] -12; - return tagLength + 14 + (tagLength % 8 == 0 ? 0 : (8 - tagLength % 8)); - //return (int)(header[offset + 2] * 256 + (int)header[offset + 3] + 2); + + // sm4加密方式的密文为16的整数倍 + return 14 + (tagLength % 16 == 0 ? tagLength : (tagLength / 16 + 1) * 16); } @@ -62,11 +65,20 @@ String exist = "0"; //数据缓存 0:不存在,1:存在 //对tag进行TEA解密 + /* Byte[] dat = new Byte[data.Length / 2 - 18]; Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); TEA.decrypt(ref dat, dat.Length); String settings = BitConverter.ToString(dat, 0, dat.Length).Replace("-", "").Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); + */ + + //对tag进行sm4解密 + Byte[] dat = new Byte[data.Length / 2 - 18]; + Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); + + String plainText = SM4Utils.sm4Decrypt(dat, deviceId); + String settings = plainText.Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); result = Common.getDeviceTypeByPdu(pduType); result += ":" + preamble + "," + version + "," + diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/SensorHub.Servers/CasicReceiveFilter.cs b/SensorHub.Servers/CasicReceiveFilter.cs index 6b270ce..43c1bfd 100644 --- a/SensorHub.Servers/CasicReceiveFilter.cs +++ b/SensorHub.Servers/CasicReceiveFilter.cs @@ -6,6 +6,8 @@ using SuperSocket.SocketBase.Protocol; using SuperSocket.Common; using SensorHub.Utility; +using SensorHub.Servers.SM4; + namespace SensorHub.Servers { @@ -20,8 +22,9 @@ protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { int tagLength = (int)header[offset + 2] * 256 + (int)header[offset + 3] -12; - return tagLength + 14 + (tagLength % 8 == 0 ? 0 : (8 - tagLength % 8)); - //return (int)(header[offset + 2] * 256 + (int)header[offset + 3] + 2); + + // sm4加密方式的密文为16的整数倍 + return 14 + (tagLength % 16 == 0 ? tagLength : (tagLength / 16 + 1) * 16); } @@ -62,11 +65,20 @@ String exist = "0"; //数据缓存 0:不存在,1:存在 //对tag进行TEA解密 + /* Byte[] dat = new Byte[data.Length / 2 - 18]; Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); TEA.decrypt(ref dat, dat.Length); String settings = BitConverter.ToString(dat, 0, dat.Length).Replace("-", "").Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); + */ + + //对tag进行sm4解密 + Byte[] dat = new Byte[data.Length / 2 - 18]; + Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); + + String plainText = SM4Utils.sm4Decrypt(dat, deviceId); + String settings = plainText.Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); result = Common.getDeviceTypeByPdu(pduType); result += ":" + preamble + "," + version + "," + diff --git a/SensorHub.Servers/Common.cs b/SensorHub.Servers/Common.cs index 6fbe9e7..af124ab 100644 --- a/SensorHub.Servers/Common.cs +++ b/SensorHub.Servers/Common.cs @@ -15,6 +15,8 @@ using Microsoft.Win32; using System.Threading; using SensorHub.Servers.SM4; +using Newtonsoft.Json.Linq; +using AepSdk.Apis; namespace SensorHub.Servers { @@ -175,9 +177,10 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -236,9 +239,10 @@ session.Logger.Info("afcrc: " + afcrc); String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 session.Logger.Info(ret + ": " + strBase64Value); - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -288,6 +292,29 @@ return result; } + public static int SendAepCommand(CasicSession session, String strValue, String deviceId) + { + string operatorId = ConfigurationManager.AppSettings["operatorId"]; + Int32 productId = Int32.Parse(ConfigurationManager.AppSettings["productId"]); + + JObject body = new JObject(); + JObject command = new JObject(); + JObject paras = new JObject(); + paras.Add("Value", strValue); // 透传的指令内容 加密后的base64字符串 参数名根据profile文件来确定 + command.Add("paras", paras); + command.Add("serviceId", "Config"); // 对应profile中的服务ID + command.Add("method", "Config"); // 对应profile中的能力 + + body.Add("command", command); + body.Add("deviceId", deviceId); + body.Add("operator", operatorId); // 对应profile中的服务ID + body.Add("productId", productId); // 对应profile中的能力 + + string ret = AepDeviceCommand.CreateCommandLwm2mProfile(JsonConvert.SerializeObject(body)); + session.Logger.Info(ret); + return Int16.Parse(JObject.Parse(ret)["code"].ToString()); + } + public static void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag) { if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发 @@ -1046,9 +1073,11 @@ if (!String.IsNullOrEmpty(softwareVersion))//有上传版本号,进行升级回复 { //读取文件 - //String path = Directory.GetCurrentDirectory(); + // String path = Directory.GetCurrentDirectory(); String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]); path += "\\Update\\" + devName; + + // string path = "C:\\casic\\tanyue\\Workspace VS\\SensorHub\\bin\\Update\\" + devName; String lastestFilePath = String.Empty; var files = Directory.GetFiles(path); @@ -1160,7 +1189,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildUpgradeConfigFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1196,11 +1225,9 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", "")); - byte[] result = frameEncrypt(updateConfig); + byte[] result = frameEncryptSM4(updateConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") { @@ -1209,8 +1236,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1226,7 +1254,7 @@ //不需要升级 session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", "")); - byte[] result = frameEncrypt(config); + byte[] result = frameEncryptSM4(config); byte[] afcrc = CRC(result); //session.Send(CRC(result), 0, result.Length + 2); @@ -1238,8 +1266,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1258,7 +1287,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildHeaderFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1288,11 +1317,10 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", "")); - byte[] result = frameEncrypt(dataConfig); + // 采用SM4加密方式 + byte[] result = frameEncryptSM4(dataConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") @@ -1302,8 +1330,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1363,6 +1392,24 @@ return result; } + //数据帧SM4加密 + private static byte[] frameEncryptSM4(byte[] frame) + { + byte[] tag = new byte[frame.Length - 16]; + byte[] enTag; + + Array.Copy(frame, 16, tag, 0, frame.Length - 16); + + // 使用SM4加密方式加密Tag部分 密钥固定在配置文件中 devCode参数不用传 + enTag = SM4Utils.sm4Encrypt(tag, ""); + + byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length]; + Array.Copy(frame, result, 16); + enTag.CopyTo(result, 16); + + return result; + } + /// /// 获取服务安装路径 diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/SensorHub.Servers/CasicReceiveFilter.cs b/SensorHub.Servers/CasicReceiveFilter.cs index 6b270ce..43c1bfd 100644 --- a/SensorHub.Servers/CasicReceiveFilter.cs +++ b/SensorHub.Servers/CasicReceiveFilter.cs @@ -6,6 +6,8 @@ using SuperSocket.SocketBase.Protocol; using SuperSocket.Common; using SensorHub.Utility; +using SensorHub.Servers.SM4; + namespace SensorHub.Servers { @@ -20,8 +22,9 @@ protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { int tagLength = (int)header[offset + 2] * 256 + (int)header[offset + 3] -12; - return tagLength + 14 + (tagLength % 8 == 0 ? 0 : (8 - tagLength % 8)); - //return (int)(header[offset + 2] * 256 + (int)header[offset + 3] + 2); + + // sm4加密方式的密文为16的整数倍 + return 14 + (tagLength % 16 == 0 ? tagLength : (tagLength / 16 + 1) * 16); } @@ -62,11 +65,20 @@ String exist = "0"; //数据缓存 0:不存在,1:存在 //对tag进行TEA解密 + /* Byte[] dat = new Byte[data.Length / 2 - 18]; Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); TEA.decrypt(ref dat, dat.Length); String settings = BitConverter.ToString(dat, 0, dat.Length).Replace("-", "").Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); + */ + + //对tag进行sm4解密 + Byte[] dat = new Byte[data.Length / 2 - 18]; + Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); + + String plainText = SM4Utils.sm4Decrypt(dat, deviceId); + String settings = plainText.Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); result = Common.getDeviceTypeByPdu(pduType); result += ":" + preamble + "," + version + "," + diff --git a/SensorHub.Servers/Common.cs b/SensorHub.Servers/Common.cs index 6fbe9e7..af124ab 100644 --- a/SensorHub.Servers/Common.cs +++ b/SensorHub.Servers/Common.cs @@ -15,6 +15,8 @@ using Microsoft.Win32; using System.Threading; using SensorHub.Servers.SM4; +using Newtonsoft.Json.Linq; +using AepSdk.Apis; namespace SensorHub.Servers { @@ -175,9 +177,10 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -236,9 +239,10 @@ session.Logger.Info("afcrc: " + afcrc); String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 session.Logger.Info(ret + ": " + strBase64Value); - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -288,6 +292,29 @@ return result; } + public static int SendAepCommand(CasicSession session, String strValue, String deviceId) + { + string operatorId = ConfigurationManager.AppSettings["operatorId"]; + Int32 productId = Int32.Parse(ConfigurationManager.AppSettings["productId"]); + + JObject body = new JObject(); + JObject command = new JObject(); + JObject paras = new JObject(); + paras.Add("Value", strValue); // 透传的指令内容 加密后的base64字符串 参数名根据profile文件来确定 + command.Add("paras", paras); + command.Add("serviceId", "Config"); // 对应profile中的服务ID + command.Add("method", "Config"); // 对应profile中的能力 + + body.Add("command", command); + body.Add("deviceId", deviceId); + body.Add("operator", operatorId); // 对应profile中的服务ID + body.Add("productId", productId); // 对应profile中的能力 + + string ret = AepDeviceCommand.CreateCommandLwm2mProfile(JsonConvert.SerializeObject(body)); + session.Logger.Info(ret); + return Int16.Parse(JObject.Parse(ret)["code"].ToString()); + } + public static void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag) { if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发 @@ -1046,9 +1073,11 @@ if (!String.IsNullOrEmpty(softwareVersion))//有上传版本号,进行升级回复 { //读取文件 - //String path = Directory.GetCurrentDirectory(); + // String path = Directory.GetCurrentDirectory(); String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]); path += "\\Update\\" + devName; + + // string path = "C:\\casic\\tanyue\\Workspace VS\\SensorHub\\bin\\Update\\" + devName; String lastestFilePath = String.Empty; var files = Directory.GetFiles(path); @@ -1160,7 +1189,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildUpgradeConfigFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1196,11 +1225,9 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", "")); - byte[] result = frameEncrypt(updateConfig); + byte[] result = frameEncryptSM4(updateConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") { @@ -1209,8 +1236,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1226,7 +1254,7 @@ //不需要升级 session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", "")); - byte[] result = frameEncrypt(config); + byte[] result = frameEncryptSM4(config); byte[] afcrc = CRC(result); //session.Send(CRC(result), 0, result.Length + 2); @@ -1238,8 +1266,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1258,7 +1287,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildHeaderFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1288,11 +1317,10 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", "")); - byte[] result = frameEncrypt(dataConfig); + // 采用SM4加密方式 + byte[] result = frameEncryptSM4(dataConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") @@ -1302,8 +1330,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1363,6 +1392,24 @@ return result; } + //数据帧SM4加密 + private static byte[] frameEncryptSM4(byte[] frame) + { + byte[] tag = new byte[frame.Length - 16]; + byte[] enTag; + + Array.Copy(frame, 16, tag, 0, frame.Length - 16); + + // 使用SM4加密方式加密Tag部分 密钥固定在配置文件中 devCode参数不用传 + enTag = SM4Utils.sm4Encrypt(tag, ""); + + byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length]; + Array.Copy(frame, result, 16); + enTag.CopyTo(result, 16); + + return result; + } + /// /// 获取服务安装路径 diff --git a/SensorHub.Servers/SM4/SM4Utils.cs b/SensorHub.Servers/SM4/SM4Utils.cs index f96b6b3..006aa99 100644 --- a/SensorHub.Servers/SM4/SM4Utils.cs +++ b/SensorHub.Servers/SM4/SM4Utils.cs @@ -14,11 +14,14 @@ { public static byte[] sm4Encrypt(byte[] plainBytes, String devcode) { + /* String secretKey = getSecretKeyByDevcode(devcode); if (secretKey == "") { secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; } + */ + String secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; SM4_Context ctx = new SM4_Context(); ctx.isPadding = true; diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/SensorHub.Servers/CasicReceiveFilter.cs b/SensorHub.Servers/CasicReceiveFilter.cs index 6b270ce..43c1bfd 100644 --- a/SensorHub.Servers/CasicReceiveFilter.cs +++ b/SensorHub.Servers/CasicReceiveFilter.cs @@ -6,6 +6,8 @@ using SuperSocket.SocketBase.Protocol; using SuperSocket.Common; using SensorHub.Utility; +using SensorHub.Servers.SM4; + namespace SensorHub.Servers { @@ -20,8 +22,9 @@ protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { int tagLength = (int)header[offset + 2] * 256 + (int)header[offset + 3] -12; - return tagLength + 14 + (tagLength % 8 == 0 ? 0 : (8 - tagLength % 8)); - //return (int)(header[offset + 2] * 256 + (int)header[offset + 3] + 2); + + // sm4加密方式的密文为16的整数倍 + return 14 + (tagLength % 16 == 0 ? tagLength : (tagLength / 16 + 1) * 16); } @@ -62,11 +65,20 @@ String exist = "0"; //数据缓存 0:不存在,1:存在 //对tag进行TEA解密 + /* Byte[] dat = new Byte[data.Length / 2 - 18]; Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); TEA.decrypt(ref dat, dat.Length); String settings = BitConverter.ToString(dat, 0, dat.Length).Replace("-", "").Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); + */ + + //对tag进行sm4解密 + Byte[] dat = new Byte[data.Length / 2 - 18]; + Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); + + String plainText = SM4Utils.sm4Decrypt(dat, deviceId); + String settings = plainText.Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); result = Common.getDeviceTypeByPdu(pduType); result += ":" + preamble + "," + version + "," + diff --git a/SensorHub.Servers/Common.cs b/SensorHub.Servers/Common.cs index 6fbe9e7..af124ab 100644 --- a/SensorHub.Servers/Common.cs +++ b/SensorHub.Servers/Common.cs @@ -15,6 +15,8 @@ using Microsoft.Win32; using System.Threading; using SensorHub.Servers.SM4; +using Newtonsoft.Json.Linq; +using AepSdk.Apis; namespace SensorHub.Servers { @@ -175,9 +177,10 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -236,9 +239,10 @@ session.Logger.Info("afcrc: " + afcrc); String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 session.Logger.Info(ret + ": " + strBase64Value); - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -288,6 +292,29 @@ return result; } + public static int SendAepCommand(CasicSession session, String strValue, String deviceId) + { + string operatorId = ConfigurationManager.AppSettings["operatorId"]; + Int32 productId = Int32.Parse(ConfigurationManager.AppSettings["productId"]); + + JObject body = new JObject(); + JObject command = new JObject(); + JObject paras = new JObject(); + paras.Add("Value", strValue); // 透传的指令内容 加密后的base64字符串 参数名根据profile文件来确定 + command.Add("paras", paras); + command.Add("serviceId", "Config"); // 对应profile中的服务ID + command.Add("method", "Config"); // 对应profile中的能力 + + body.Add("command", command); + body.Add("deviceId", deviceId); + body.Add("operator", operatorId); // 对应profile中的服务ID + body.Add("productId", productId); // 对应profile中的能力 + + string ret = AepDeviceCommand.CreateCommandLwm2mProfile(JsonConvert.SerializeObject(body)); + session.Logger.Info(ret); + return Int16.Parse(JObject.Parse(ret)["code"].ToString()); + } + public static void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag) { if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发 @@ -1046,9 +1073,11 @@ if (!String.IsNullOrEmpty(softwareVersion))//有上传版本号,进行升级回复 { //读取文件 - //String path = Directory.GetCurrentDirectory(); + // String path = Directory.GetCurrentDirectory(); String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]); path += "\\Update\\" + devName; + + // string path = "C:\\casic\\tanyue\\Workspace VS\\SensorHub\\bin\\Update\\" + devName; String lastestFilePath = String.Empty; var files = Directory.GetFiles(path); @@ -1160,7 +1189,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildUpgradeConfigFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1196,11 +1225,9 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", "")); - byte[] result = frameEncrypt(updateConfig); + byte[] result = frameEncryptSM4(updateConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") { @@ -1209,8 +1236,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1226,7 +1254,7 @@ //不需要升级 session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", "")); - byte[] result = frameEncrypt(config); + byte[] result = frameEncryptSM4(config); byte[] afcrc = CRC(result); //session.Send(CRC(result), 0, result.Length + 2); @@ -1238,8 +1266,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1258,7 +1287,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildHeaderFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1288,11 +1317,10 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", "")); - byte[] result = frameEncrypt(dataConfig); + // 采用SM4加密方式 + byte[] result = frameEncryptSM4(dataConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") @@ -1302,8 +1330,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1363,6 +1392,24 @@ return result; } + //数据帧SM4加密 + private static byte[] frameEncryptSM4(byte[] frame) + { + byte[] tag = new byte[frame.Length - 16]; + byte[] enTag; + + Array.Copy(frame, 16, tag, 0, frame.Length - 16); + + // 使用SM4加密方式加密Tag部分 密钥固定在配置文件中 devCode参数不用传 + enTag = SM4Utils.sm4Encrypt(tag, ""); + + byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length]; + Array.Copy(frame, result, 16); + enTag.CopyTo(result, 16); + + return result; + } + /// /// 获取服务安装路径 diff --git a/SensorHub.Servers/SM4/SM4Utils.cs b/SensorHub.Servers/SM4/SM4Utils.cs index f96b6b3..006aa99 100644 --- a/SensorHub.Servers/SM4/SM4Utils.cs +++ b/SensorHub.Servers/SM4/SM4Utils.cs @@ -14,11 +14,14 @@ { public static byte[] sm4Encrypt(byte[] plainBytes, String devcode) { + /* String secretKey = getSecretKeyByDevcode(devcode); if (secretKey == "") { secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; } + */ + String secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; SM4_Context ctx = new SM4_Context(); ctx.isPadding = true; diff --git a/SensorHub.Servers/SensorHub.Servers.csproj b/SensorHub.Servers/SensorHub.Servers.csproj index b6236fa..4789683 100644 --- a/SensorHub.Servers/SensorHub.Servers.csproj +++ b/SensorHub.Servers/SensorHub.Servers.csproj @@ -127,6 +127,8 @@ + + diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/SensorHub.Servers/CasicReceiveFilter.cs b/SensorHub.Servers/CasicReceiveFilter.cs index 6b270ce..43c1bfd 100644 --- a/SensorHub.Servers/CasicReceiveFilter.cs +++ b/SensorHub.Servers/CasicReceiveFilter.cs @@ -6,6 +6,8 @@ using SuperSocket.SocketBase.Protocol; using SuperSocket.Common; using SensorHub.Utility; +using SensorHub.Servers.SM4; + namespace SensorHub.Servers { @@ -20,8 +22,9 @@ protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { int tagLength = (int)header[offset + 2] * 256 + (int)header[offset + 3] -12; - return tagLength + 14 + (tagLength % 8 == 0 ? 0 : (8 - tagLength % 8)); - //return (int)(header[offset + 2] * 256 + (int)header[offset + 3] + 2); + + // sm4加密方式的密文为16的整数倍 + return 14 + (tagLength % 16 == 0 ? tagLength : (tagLength / 16 + 1) * 16); } @@ -62,11 +65,20 @@ String exist = "0"; //数据缓存 0:不存在,1:存在 //对tag进行TEA解密 + /* Byte[] dat = new Byte[data.Length / 2 - 18]; Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); TEA.decrypt(ref dat, dat.Length); String settings = BitConverter.ToString(dat, 0, dat.Length).Replace("-", "").Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); + */ + + //对tag进行sm4解密 + Byte[] dat = new Byte[data.Length / 2 - 18]; + Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); + + String plainText = SM4Utils.sm4Decrypt(dat, deviceId); + String settings = plainText.Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); result = Common.getDeviceTypeByPdu(pduType); result += ":" + preamble + "," + version + "," + diff --git a/SensorHub.Servers/Common.cs b/SensorHub.Servers/Common.cs index 6fbe9e7..af124ab 100644 --- a/SensorHub.Servers/Common.cs +++ b/SensorHub.Servers/Common.cs @@ -15,6 +15,8 @@ using Microsoft.Win32; using System.Threading; using SensorHub.Servers.SM4; +using Newtonsoft.Json.Linq; +using AepSdk.Apis; namespace SensorHub.Servers { @@ -175,9 +177,10 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -236,9 +239,10 @@ session.Logger.Info("afcrc: " + afcrc); String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 session.Logger.Info(ret + ": " + strBase64Value); - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -288,6 +292,29 @@ return result; } + public static int SendAepCommand(CasicSession session, String strValue, String deviceId) + { + string operatorId = ConfigurationManager.AppSettings["operatorId"]; + Int32 productId = Int32.Parse(ConfigurationManager.AppSettings["productId"]); + + JObject body = new JObject(); + JObject command = new JObject(); + JObject paras = new JObject(); + paras.Add("Value", strValue); // 透传的指令内容 加密后的base64字符串 参数名根据profile文件来确定 + command.Add("paras", paras); + command.Add("serviceId", "Config"); // 对应profile中的服务ID + command.Add("method", "Config"); // 对应profile中的能力 + + body.Add("command", command); + body.Add("deviceId", deviceId); + body.Add("operator", operatorId); // 对应profile中的服务ID + body.Add("productId", productId); // 对应profile中的能力 + + string ret = AepDeviceCommand.CreateCommandLwm2mProfile(JsonConvert.SerializeObject(body)); + session.Logger.Info(ret); + return Int16.Parse(JObject.Parse(ret)["code"].ToString()); + } + public static void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag) { if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发 @@ -1046,9 +1073,11 @@ if (!String.IsNullOrEmpty(softwareVersion))//有上传版本号,进行升级回复 { //读取文件 - //String path = Directory.GetCurrentDirectory(); + // String path = Directory.GetCurrentDirectory(); String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]); path += "\\Update\\" + devName; + + // string path = "C:\\casic\\tanyue\\Workspace VS\\SensorHub\\bin\\Update\\" + devName; String lastestFilePath = String.Empty; var files = Directory.GetFiles(path); @@ -1160,7 +1189,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildUpgradeConfigFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1196,11 +1225,9 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", "")); - byte[] result = frameEncrypt(updateConfig); + byte[] result = frameEncryptSM4(updateConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") { @@ -1209,8 +1236,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1226,7 +1254,7 @@ //不需要升级 session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", "")); - byte[] result = frameEncrypt(config); + byte[] result = frameEncryptSM4(config); byte[] afcrc = CRC(result); //session.Send(CRC(result), 0, result.Length + 2); @@ -1238,8 +1266,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1258,7 +1287,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildHeaderFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1288,11 +1317,10 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", "")); - byte[] result = frameEncrypt(dataConfig); + // 采用SM4加密方式 + byte[] result = frameEncryptSM4(dataConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") @@ -1302,8 +1330,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1363,6 +1392,24 @@ return result; } + //数据帧SM4加密 + private static byte[] frameEncryptSM4(byte[] frame) + { + byte[] tag = new byte[frame.Length - 16]; + byte[] enTag; + + Array.Copy(frame, 16, tag, 0, frame.Length - 16); + + // 使用SM4加密方式加密Tag部分 密钥固定在配置文件中 devCode参数不用传 + enTag = SM4Utils.sm4Encrypt(tag, ""); + + byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length]; + Array.Copy(frame, result, 16); + enTag.CopyTo(result, 16); + + return result; + } + /// /// 获取服务安装路径 diff --git a/SensorHub.Servers/SM4/SM4Utils.cs b/SensorHub.Servers/SM4/SM4Utils.cs index f96b6b3..006aa99 100644 --- a/SensorHub.Servers/SM4/SM4Utils.cs +++ b/SensorHub.Servers/SM4/SM4Utils.cs @@ -14,11 +14,14 @@ { public static byte[] sm4Encrypt(byte[] plainBytes, String devcode) { + /* String secretKey = getSecretKeyByDevcode(devcode); if (secretKey == "") { secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; } + */ + String secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; SM4_Context ctx = new SM4_Context(); ctx.isPadding = true; diff --git a/SensorHub.Servers/SensorHub.Servers.csproj b/SensorHub.Servers/SensorHub.Servers.csproj index b6236fa..4789683 100644 --- a/SensorHub.Servers/SensorHub.Servers.csproj +++ b/SensorHub.Servers/SensorHub.Servers.csproj @@ -127,6 +127,8 @@ + + diff --git a/SensorHub.Servers/TelecomReceiveFilter.cs b/SensorHub.Servers/TelecomReceiveFilter.cs index ba17e7e..dd3b850 100644 --- a/SensorHub.Servers/TelecomReceiveFilter.cs +++ b/SensorHub.Servers/TelecomReceiveFilter.cs @@ -18,10 +18,11 @@ public class TelecomReceiveFilter : BeginEndMarkReceiveFilter { //开始和结束标记也可以是两个或两个以上的字节 + // 改成电信AEP平台后传入的data有变化 通过java接口进行转发 增加了##作为帧头 **作为帧尾 private readonly static byte[] BeginMark = new byte[] { (byte)'P', (byte)'O', (byte)'S', (byte)'T' }; - private readonly static byte[] EndMark = new byte[] { (byte)'}', (byte)'}' }; + private readonly static byte[] EndMark = new byte[] { (byte)'*', (byte)'*' }; // AEP平台的结尾 + // private readonly static byte[] EndMark = new byte[] { (byte)'}', (byte)'}' }; // OC平台的结尾 private static MemoryCache memoryCache = new MemoryCache("Telecom"); - //private static MemoryCache sm4MemoryCache = new MemoryCache("SM4"); private readonly object SyncObj = new object(); public TelecomReceiveFilter() @@ -34,11 +35,18 @@ { //TODO: 通过解析到的数据来构造请求实例,并返回 String dataJson = System.Text.Encoding.Default.GetString(readBuffer); - dataJson = dataJson.Substring(dataJson.LastIndexOf('\n') + 1); + + // AEP平台对应的data部分 + int startIdx = dataJson.IndexOf("##"); + int endIdx = dataJson.IndexOf("**"); + dataJson = dataJson.Substring(dataJson.IndexOf("##") + 2, endIdx - startIdx - 2); + + // dataJson = dataJson.Substring(dataJson.LastIndexOf('\n') + 1); JObject jo = (JObject)JsonConvert.DeserializeObject(dataJson); String telecomDeviceId = jo["deviceId"].ToString();//电信平台设备编号 - String Value = jo["service"]["data"]["Value"].ToString();//{"Value":"ow=="} + String Value = jo["payload"]["serviceData"]["Value"].ToString();//{"Value":"ow=="} //AEP平台 + // String Value = jo["service"]["data"]["Value"].ToString();//{"Value":"ow=="} String result = ""; byte[] src = Convert.FromBase64String(Value); diff --git a/.gitignore b/.gitignore index 1a67bd4..baeb2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ /SensorHub.CorrRate/obj /SensorHub.Dig/obj /SensorHub.FireHydrant/obj +/SensorHub.HydrogenSulfide/bin +/SensorHub.HydrogenSulfide/obj /SensorHub.Lamp/obj /SensorHub.Lamphouse/obj /SensorHub.LampNB/obj @@ -26,8 +28,11 @@ /SensorHub.Servers/obj /SensorHub.TempHumi/obj /SensorHub.TempPressure/obj +/SensorHub.Tube/bin +/SensorHub.Tube/obj /SensorHub.Utility/obj /SensorHub.WasteGas/obj /SensorHub.WaterMeter/obj /SensorHub.Well/obj +/SensorHub.WellPlus/obj /TestClass/obj \ No newline at end of file diff --git a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs index 2bc32cf..7fdc5e8 100644 --- a/SensorHub.HydrogenSulfide/HydrogenSulfide.cs +++ b/SensorHub.HydrogenSulfide/HydrogenSulfide.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; namespace SensorHub.HydrogenSulfide { @@ -56,9 +57,14 @@ return; } + Mutex mutex = new Mutex(); + mutex.WaitOne(); + //获取电量信息,系统时间,传递给对应的handler List tags = Common.getTags(settings, session); + mutex.ReleaseMutex(); + //具体业务处理 String collectDate = ""; int cell = -1; @@ -191,8 +197,7 @@ } } - // Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); - Common.kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { diff --git a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs index 1d85286..15d7d3f 100644 --- a/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs +++ b/SensorHub.HydrogenSulfide/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ [assembly: ComVisible(false)] // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID -[assembly: Guid("d51363ce-ee08-4252-ad3a-6aef13b5df81")] +[assembly: Guid("cdae0e93-0ca1-446f-99a1-2d071f73700c")] // 程序集的版本信息由下列四个值组成: // diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj index 7bde57f..512ba4f 100644 --- a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4 diff --git a/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user new file mode 100644 index 0000000..9e692f1 --- /dev/null +++ b/SensorHub.HydrogenSulfide/SensorHub.HydrogenSulfide.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/SensorHub.Methane/Methane.cs b/SensorHub.Methane/Methane.cs index d5bf37b..5b7d69c 100644 --- a/SensorHub.Methane/Methane.cs +++ b/SensorHub.Methane/Methane.cs @@ -49,8 +49,12 @@ btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false); btPdu[1] = 0x84; - if (exist == "0")//数据没有缓存 - { + String softwareVersion = ""; + uint offset = 0; + uint size = 0; + + // if (exist == "0")//数据没有缓存 + //{ //判断是返回的设置确认数据帧, 回复第三方 if (operType == "SetResponse") { @@ -73,10 +77,6 @@ int? rsrp = null; int? snr = null; - String softwareVersion = ""; - uint offset = 0; - uint size = 0; - List eventList = new List(); List datasList = new List(); List startupList = new List(); @@ -152,6 +152,9 @@ { SoftwareVersionTag versionTag = (SoftwareVersionTag)tag; softwareVersion = versionTag.Version; + + session.Logger.Info("设备上报版本号:" + softwareVersion); + continue; } @@ -171,29 +174,32 @@ } else { - //业务处理 - UploadTag uploadTag = tag as UploadTag; - switch (uploadTag.BizType) + if (exist == "0")//数据没有缓存 { - case 5: - //气体浓度 - TagHandler methaneHandler = new MethaneTagHandler(); - methaneHandler.resolve(tag, session); + //业务处理 + UploadTag uploadTag = tag as UploadTag; + switch (uploadTag.BizType) + { + case 5: + //气体浓度 + TagHandler methaneHandler = new MethaneTagHandler(); + methaneHandler.resolve(tag, session); - DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); - for (int i = 0; i < methaneHandler.DataList.Count; i++) - { - DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); - String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") - + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); + DateTime baseTime = Convert.ToDateTime(collectDate + " " + methaneHandler.CollecTime); + for (int i = 0; i < methaneHandler.DataList.Count; i++) + { + DateTime upTime = baseTime.AddMinutes(i * methaneHandler.Interval); + String uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd") + + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss"); - datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); - } + datasList.Add(new MethaneDatasJson(uptime, (float)methaneHandler.DataList[i])); + } - break; - default: - session.Logger.Info("未知业务类型!"); - break; + break; + default: + session.Logger.Info("未知业务类型!"); + break; + } } } } @@ -201,13 +207,14 @@ // 发送到flume或者kafka Common.sendMessage(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList); + if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程 { Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source); return; } - } - + // } + Common.sendConfig(session, devCode, routeFlag, source, btPdu); } diff --git a/SensorHub.MultiLeak/MultiLeak.cs b/SensorHub.MultiLeak/MultiLeak.cs index 98ab2c4..fab2f83 100644 --- a/SensorHub.MultiLeak/MultiLeak.cs +++ b/SensorHub.MultiLeak/MultiLeak.cs @@ -551,7 +551,8 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = Common.SendNACommand(session, strBase64Value, source); + // int ret = Common.SendNACommand(session, strBase64Value, source); + int ret = Common.SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 if (ret != 201) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); diff --git a/SensorHub.Servers/AepDeviceCommand.cs b/SensorHub.Servers/AepDeviceCommand.cs new file mode 100644 index 0000000..aeb591f --- /dev/null +++ b/SensorHub.Servers/AepDeviceCommand.cs @@ -0,0 +1,150 @@ +using AepSdk.Apis.Core; +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace AepSdk.Apis +{ + class AepDeviceCommand + { + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommand(string body) + { + string path = "/aep_device_command/command"; + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190712225145"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + Console.WriteLine(response); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数productId: 类型long, 参数不可以为空 + // 描述:产品ID,必填 + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID,必填 + //参数startTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数endTime: 类型String, 参数可以为空 + // 描述:日期格式,年月日时分秒,例如:20200801120130 + //参数pageNow: 类型long, 参数可以为空 + // 描述:当前页数 + //参数pageSize: 类型long, 参数可以为空 + // 描述:每页记录数,最大40 + public static string QueryCommandList(string appKey, string appSecret, string MasterKey, string productId, string deviceId, string startTime = "", string endTime = "", string pageNow = "", string pageSize = "") + { + string path = "/aep_device_command/commands"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + param.Add("startTime", startTime); + param.Add("endTime", endTime); + param.Add("pageNow", pageNow); + param.Add("pageSize", pageSize); + + string version = "20200814163736"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数commandId: 类型String, 参数不可以为空 + // 描述:创建指令成功响应中返回的id, + //参数productId: 类型long, 参数不可以为空 + // 描述: + //参数deviceId: 类型String, 参数不可以为空 + // 描述:设备ID + public static string QueryCommand(string appKey, string appSecret, string MasterKey, string commandId, string productId, string deviceId) + { + string path = "/aep_device_command/command"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = new Dictionary(); + param.Add("commandId", commandId); + param.Add("productId", productId); + param.Add("deviceId", deviceId); + + string version = "20190712225241"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, null, version, application, key, "GET"); + if (response != null) + return response; + return null; + } + //参数MasterKey: 类型String, 参数不可以为空 + // 描述: + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CancelCommand(string appKey, string appSecret, string MasterKey, string body) + { + string path = "/aep_device_command/cancelCommand"; + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20190615023142"; + + string application = appKey; + string key = appSecret; + + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "PUT"); + if (response != null) + return response; + return null; + } + + //参数MasterKey: 类型String, 参数可以为空 + // 描述:MasterKey在该设备所属产品的概况中可以查看 + //参数body: 类型json, 参数不可以为空 + // 描述:body,具体参考平台api说明 + public static string CreateCommandLwm2mProfile(string body) + { + string path = "/aep_device_command_lwm_profile/commandLwm2mProfile"; + + string application = ConfigurationManager.AppSettings["AppKey"]; + string key = ConfigurationManager.AppSettings["AppSecret"]; + string MasterKey = ConfigurationManager.AppSettings["MasterKey"]; + + Dictionary headers = new Dictionary(); + headers.Add("MasterKey", MasterKey); + + Dictionary param = null; + string version = "20191231141545"; + + string response = AepHttpRequest.SendAepHttpRequest(path, headers, param, body, version, application, key, "POST"); + if (response != null) + return response; + return null; + } + + } +} \ No newline at end of file diff --git a/SensorHub.Servers/AepSdkCore.cs b/SensorHub.Servers/AepSdkCore.cs new file mode 100644 index 0000000..73a12c0 --- /dev/null +++ b/SensorHub.Servers/AepSdkCore.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace AepSdk.Apis.Core +{ + class AepHttpRequest + { + static long offset = 0; + static long lastGetOffsetTime = 0; + static readonly string baseUrl = ConfigurationManager.AppSettings["BaseUrl"]; + static readonly string timeUrl = "https://ag-api.ctwing.cn/echo"; + + + /// + /// 获取时间偏移量 + /// + /// 时间偏移量 + public static long GetTimeOffset() + { + long start = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + WebHeaderCollection head = null; + string response = SendHttpRequest(timeUrl, null, "application/json; charset=UTF-8", "GET", null, 5, out head); + long end = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (response != null) + { + long timeAg = Convert.ToInt64(head["x-ag-timestamp"]); + return timeAg - (end + start) / 2; + } + + return 0; + } + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method) + { + WebHeaderCollection head; + return SendAepHttpRequest(path, headers, param, body, version, application, key, method, out head); + } + + + /// + /// 发送api请求到aep + /// + /// api接口路径 + /// 请求head + /// 参数 + /// body,如果为get等没有body请求,填null + /// api接口版本,在文档中查询 + /// App Key + /// App Secret + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求结果的head出参 + /// + public static string SendAepHttpRequest(string path, Dictionary headers, Dictionary param, string body, string version, string application, string key, string method, out WebHeaderCollection head) + { + + string paramString = ""; + + if (param != null) + { + foreach (KeyValuePair kvp in param) + { + paramString += kvp.Key + "=" + kvp.Value + "&"; + } + } + + if (paramString.Length > 0) + { + paramString = paramString.Remove(paramString.Length - 1); + } + + // Console.WriteLine("paramString = " + paramString); + + + + Dictionary paramTmp = new Dictionary(); + if (headers != null) + paramTmp = paramTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + if (param != null) + paramTmp = paramTmp.Concat(param).ToDictionary(k => k.Key, v => v.Value); + + long curentTime = (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000; + if (curentTime - lastGetOffsetTime > 300 * 1000) //300秒调用一次 + { + offset = GetTimeOffset(); + lastGetOffsetTime = curentTime; + } + long timestamp = curentTime + offset; + + Dictionary headersTmp = new Dictionary(); + headersTmp.Add("application", application); + headersTmp.Add("timestamp", "" + timestamp); + headersTmp.Add("version", version); + //headersTmp.Add("Content-Type", "application/json; charset=UTF-8"); + //headersTmp.Add("Date", dataString); + headersTmp.Add("signature", Sign(paramTmp, timestamp, application, key, body)); + if (headers != null) + { + headersTmp = headersTmp.Concat(headers).ToDictionary(k => k.Key, v => v.Value); + } + + string url = baseUrl + path; + if (paramString.Length > 0) + { + url += "?" + paramString; + } + // Console.WriteLine("url = " + url); + string result = SendHttpRequest(url, headersTmp, "application/json; charset=UTF-8", method, body, 35, out head); + return result; + } + + + + /// + /// 签名算法 + /// + /// api接口参数 + /// 时间戳,毫秒级 + /// App Key + /// App secret + /// body + /// + public static string Sign(Dictionary param, long timestamp, string application, string secret, string body) + { + // 连接系统参数 + string temp = "application:" + application + "\n"; + temp += "timestamp:" + timestamp + "\n"; + + // 连接请求参数 + if (param != null) + { + var dicNew = param.OrderBy(x => x.Key, new ComparerString()).ToDictionary(x => x.Key, y => y.Value); + + foreach (KeyValuePair kvp in dicNew) + { + temp += kvp.Key + ":" + (kvp.Value == null ? "" : kvp.Value) + "\n"; + } + } + + + // 得到需要签名的字符串 + if (body != null && body.Length > 0) + { + temp += body + "\n"; + } + // Console.WriteLine("Sign string: " + temp); + + // hmac-sha1编码 + var hmacsha1 = new HMACSHA1(); + hmacsha1.Key = Encoding.UTF8.GetBytes(secret); + byte[] dataBuffer = Encoding.UTF8.GetBytes(temp); + byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); + + + // base64编码 + string encode = Convert.ToBase64String(hashBytes); + + return encode; + } + + /// + /// 处理http请求 + /// + /// 请求的url地址 + /// 协议标头 + /// 请求的内容类型 + /// 请求的类型,GET、POST、PUT、DELETE + /// 请求的数据流 + /// 请求的超时时间(秒) + /// http POST成功后返回的数据,失败抛异常 + public static string SendHttpRequest(string url, Dictionary headers, string contentType, string method, string dataStream, int timeout, out WebHeaderCollection head) + { + System.GC.Collect();//垃圾回收,回收没有正常关闭的http链接 + HttpWebRequest request = null; + HttpWebResponse response = null; + Stream reqStream = null; + try + { + //设置最大链接数 + ServicePointManager.DefaultConnectionLimit = 200; + //设置https验证方式 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CertificateValidation); + } + request = (HttpWebRequest)WebRequest.Create(url); + + //HttpWebRequest 相关属性 + request.Method = method; + request.Timeout = timeout * 1000; + request.ContentType = contentType; + if (headers != null) + { + //配置协议标头 + foreach (KeyValuePair kvp in headers) + { + request.Headers.Add(kvp.Key, kvp.Value); + } + } + + byte[] data = null; + if (dataStream != null) + { + data = System.Text.Encoding.UTF8.GetBytes(dataStream); + request.ContentLength = data.Length; + } + + if (data != null) + { + //写入数据 + reqStream = request.GetRequestStream(); + reqStream.Write(data, 0, data.Length); + reqStream.Close(); + } + + head = null; + //返回数据 + response = (HttpWebResponse)request.GetResponse(); + if (response != null) + { + head = response.Headers; + Stream stream = response.GetResponseStream(); + StreamReader sr = new StreamReader(stream, Encoding.UTF8); + string result = sr.ReadToEnd(); + sr.Close(); + //关闭连接和流 + response.Close(); + return result; + } + else + { + head = null; + return String.Empty; + } + + + } + //处理多线程模式下线程中止 + //catch (System.Threading.ThreadAbortException e) + //{ + // System.Threading.Thread.ResetAbort(); + //} + catch (WebException e) + { + head = null; + response = (HttpWebResponse)e.Response; + if (response != null) + { + head = response.Headers; + } + throw e; + } + catch (Exception e) + { + throw new HttpServiceException(e.ToString()); + } + finally + { + if (request != null) + { + request.Abort(); + } + } + } + + /* 忽略证书认证错误 + * .NET的SSL通信过程中,使用的证书可能存在各种问题 + * 此方法可以跳过服务器证书验证,完成正常通信。*/ + private static bool CertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) + { + // 认证正常,没有错误 + return true; + } + } + + class HttpServiceException : Exception + { + public HttpServiceException(string msg) : base(msg) + { + + } + } + + public class ComparerString : IComparer + { + public int Compare(String x, String y) + { + return string.CompareOrdinal(x, y); + } + } +} \ No newline at end of file diff --git a/SensorHub.Servers/CasicReceiveFilter.cs b/SensorHub.Servers/CasicReceiveFilter.cs index 6b270ce..43c1bfd 100644 --- a/SensorHub.Servers/CasicReceiveFilter.cs +++ b/SensorHub.Servers/CasicReceiveFilter.cs @@ -6,6 +6,8 @@ using SuperSocket.SocketBase.Protocol; using SuperSocket.Common; using SensorHub.Utility; +using SensorHub.Servers.SM4; + namespace SensorHub.Servers { @@ -20,8 +22,9 @@ protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length) { int tagLength = (int)header[offset + 2] * 256 + (int)header[offset + 3] -12; - return tagLength + 14 + (tagLength % 8 == 0 ? 0 : (8 - tagLength % 8)); - //return (int)(header[offset + 2] * 256 + (int)header[offset + 3] + 2); + + // sm4加密方式的密文为16的整数倍 + return 14 + (tagLength % 16 == 0 ? tagLength : (tagLength / 16 + 1) * 16); } @@ -62,11 +65,20 @@ String exist = "0"; //数据缓存 0:不存在,1:存在 //对tag进行TEA解密 + /* Byte[] dat = new Byte[data.Length / 2 - 18]; Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); TEA.decrypt(ref dat, dat.Length); String settings = BitConverter.ToString(dat, 0, dat.Length).Replace("-", "").Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); + */ + + //对tag进行sm4解密 + Byte[] dat = new Byte[data.Length / 2 - 18]; + Array.Copy(src, 16, dat, 0, data.Length / 2 - 18); + + String plainText = SM4Utils.sm4Decrypt(dat, deviceId); + String settings = plainText.Substring(0, Convert.ToInt32(leng, 16) * 2 - 12 * 2); result = Common.getDeviceTypeByPdu(pduType); result += ":" + preamble + "," + version + "," + diff --git a/SensorHub.Servers/Common.cs b/SensorHub.Servers/Common.cs index 6fbe9e7..af124ab 100644 --- a/SensorHub.Servers/Common.cs +++ b/SensorHub.Servers/Common.cs @@ -15,6 +15,8 @@ using Microsoft.Win32; using System.Threading; using SensorHub.Servers.SM4; +using Newtonsoft.Json.Linq; +using AepSdk.Apis; namespace SensorHub.Servers { @@ -175,9 +177,10 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -236,9 +239,10 @@ session.Logger.Info("afcrc: " + afcrc); String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 session.Logger.Info(ret + ": " + strBase64Value); - if (ret != 201) + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -288,6 +292,29 @@ return result; } + public static int SendAepCommand(CasicSession session, String strValue, String deviceId) + { + string operatorId = ConfigurationManager.AppSettings["operatorId"]; + Int32 productId = Int32.Parse(ConfigurationManager.AppSettings["productId"]); + + JObject body = new JObject(); + JObject command = new JObject(); + JObject paras = new JObject(); + paras.Add("Value", strValue); // 透传的指令内容 加密后的base64字符串 参数名根据profile文件来确定 + command.Add("paras", paras); + command.Add("serviceId", "Config"); // 对应profile中的服务ID + command.Add("method", "Config"); // 对应profile中的能力 + + body.Add("command", command); + body.Add("deviceId", deviceId); + body.Add("operator", operatorId); // 对应profile中的服务ID + body.Add("productId", productId); // 对应profile中的能力 + + string ret = AepDeviceCommand.CreateCommandLwm2mProfile(JsonConvert.SerializeObject(body)); + session.Logger.Info(ret); + return Int16.Parse(JObject.Parse(ret)["code"].ToString()); + } + public static void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag) { if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发 @@ -1046,9 +1073,11 @@ if (!String.IsNullOrEmpty(softwareVersion))//有上传版本号,进行升级回复 { //读取文件 - //String path = Directory.GetCurrentDirectory(); + // String path = Directory.GetCurrentDirectory(); String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]); path += "\\Update\\" + devName; + + // string path = "C:\\casic\\tanyue\\Workspace VS\\SensorHub\\bin\\Update\\" + devName; String lastestFilePath = String.Empty; var files = Directory.GetFiles(path); @@ -1160,7 +1189,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildUpgradeConfigFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1196,11 +1225,9 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", "")); - byte[] result = frameEncrypt(updateConfig); + byte[] result = frameEncryptSM4(updateConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") { @@ -1209,8 +1236,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1226,7 +1254,7 @@ //不需要升级 session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", "")); - byte[] result = frameEncrypt(config); + byte[] result = frameEncryptSM4(config); byte[] afcrc = CRC(result); //session.Send(CRC(result), 0, result.Length + 2); @@ -1238,8 +1266,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1258,7 +1287,7 @@ CasicSender sender = new CasicSender(null); byte[] config = sender.buildHeaderFrame(devCode); - config[10] = 0x03;//通信方式,nb + config[10] = 0x03;//通信方式 = 运营商网络(NB 4G) btPdu.CopyTo(config, 13); @@ -1288,11 +1317,10 @@ session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", "")); - byte[] result = frameEncrypt(dataConfig); + // 采用SM4加密方式 + byte[] result = frameEncryptSM4(dataConfig); byte[] afcrc = CRC(result); - //session.Send(CRC(result), 0, result.Length + 2); - //TODO:发送数据 if (source == "OTHER") @@ -1302,8 +1330,9 @@ else { String strBase64Value = Convert.ToBase64String(afcrc); - int ret = SendNACommand(session, strBase64Value, source); - if (ret != 201) + // int ret = SendNACommand(session, strBase64Value, source); + int ret = SendAepCommand(session, strBase64Value, source); // 新AEP平台指令 + if (ret != 0) { session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret); } @@ -1363,6 +1392,24 @@ return result; } + //数据帧SM4加密 + private static byte[] frameEncryptSM4(byte[] frame) + { + byte[] tag = new byte[frame.Length - 16]; + byte[] enTag; + + Array.Copy(frame, 16, tag, 0, frame.Length - 16); + + // 使用SM4加密方式加密Tag部分 密钥固定在配置文件中 devCode参数不用传 + enTag = SM4Utils.sm4Encrypt(tag, ""); + + byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length]; + Array.Copy(frame, result, 16); + enTag.CopyTo(result, 16); + + return result; + } + /// /// 获取服务安装路径 diff --git a/SensorHub.Servers/SM4/SM4Utils.cs b/SensorHub.Servers/SM4/SM4Utils.cs index f96b6b3..006aa99 100644 --- a/SensorHub.Servers/SM4/SM4Utils.cs +++ b/SensorHub.Servers/SM4/SM4Utils.cs @@ -14,11 +14,14 @@ { public static byte[] sm4Encrypt(byte[] plainBytes, String devcode) { + /* String secretKey = getSecretKeyByDevcode(devcode); if (secretKey == "") { secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; } + */ + String secretKey = System.Configuration.ConfigurationManager.AppSettings["secretKey"]; SM4_Context ctx = new SM4_Context(); ctx.isPadding = true; diff --git a/SensorHub.Servers/SensorHub.Servers.csproj b/SensorHub.Servers/SensorHub.Servers.csproj index b6236fa..4789683 100644 --- a/SensorHub.Servers/SensorHub.Servers.csproj +++ b/SensorHub.Servers/SensorHub.Servers.csproj @@ -127,6 +127,8 @@ + + diff --git a/SensorHub.Servers/TelecomReceiveFilter.cs b/SensorHub.Servers/TelecomReceiveFilter.cs index ba17e7e..dd3b850 100644 --- a/SensorHub.Servers/TelecomReceiveFilter.cs +++ b/SensorHub.Servers/TelecomReceiveFilter.cs @@ -18,10 +18,11 @@ public class TelecomReceiveFilter : BeginEndMarkReceiveFilter { //开始和结束标记也可以是两个或两个以上的字节 + // 改成电信AEP平台后传入的data有变化 通过java接口进行转发 增加了##作为帧头 **作为帧尾 private readonly static byte[] BeginMark = new byte[] { (byte)'P', (byte)'O', (byte)'S', (byte)'T' }; - private readonly static byte[] EndMark = new byte[] { (byte)'}', (byte)'}' }; + private readonly static byte[] EndMark = new byte[] { (byte)'*', (byte)'*' }; // AEP平台的结尾 + // private readonly static byte[] EndMark = new byte[] { (byte)'}', (byte)'}' }; // OC平台的结尾 private static MemoryCache memoryCache = new MemoryCache("Telecom"); - //private static MemoryCache sm4MemoryCache = new MemoryCache("SM4"); private readonly object SyncObj = new object(); public TelecomReceiveFilter() @@ -34,11 +35,18 @@ { //TODO: 通过解析到的数据来构造请求实例,并返回 String dataJson = System.Text.Encoding.Default.GetString(readBuffer); - dataJson = dataJson.Substring(dataJson.LastIndexOf('\n') + 1); + + // AEP平台对应的data部分 + int startIdx = dataJson.IndexOf("##"); + int endIdx = dataJson.IndexOf("**"); + dataJson = dataJson.Substring(dataJson.IndexOf("##") + 2, endIdx - startIdx - 2); + + // dataJson = dataJson.Substring(dataJson.LastIndexOf('\n') + 1); JObject jo = (JObject)JsonConvert.DeserializeObject(dataJson); String telecomDeviceId = jo["deviceId"].ToString();//电信平台设备编号 - String Value = jo["service"]["data"]["Value"].ToString();//{"Value":"ow=="} + String Value = jo["payload"]["serviceData"]["Value"].ToString();//{"Value":"ow=="} //AEP平台 + // String Value = jo["service"]["data"]["Value"].ToString();//{"Value":"ow=="} String result = ""; byte[] src = Convert.FromBase64String(Value); diff --git a/SensorHub.Tube/SensorHub.Tube.csproj b/SensorHub.Tube/SensorHub.Tube.csproj index a1c0b1b..e752b2d 100644 --- a/SensorHub.Tube/SensorHub.Tube.csproj +++ b/SensorHub.Tube/SensorHub.Tube.csproj @@ -17,7 +17,7 @@ true full false - bin\Debug\ + ..\bin\ DEBUG;TRACE prompt 4