目 錄
12.服務接口的開發,以及與雲端雙向互動... 2
12.1 概述... 2
12.2 裝置連結器... 2
12.3 服務連結器... 3
12.4 場景假設... 3
12.5 裝置驅動開發及注意事項... 4
12.6 服務執行個體開發及注意事項... 4
12.7 宿主程式服務執行個體配置注意事項... 8
12.8 運作效果... 9
12.服務接口的開發,以及與雲端雙向互動
12.1 概述
服務接口IService是除裝置驅動接口IRunDevice外的特殊應用場景,例如:短信報警、LED輸出、模拟量的采集、OPC服務端/用戶端、資料的級聯轉發、以及其他的特殊應用。是基于裝置驅動接口IRunDevice的有力擴充,讓架構的功能更豐富和強大。
這篇文章主要介紹資料的轉發和控制服務,其他的服務開發與此類似。如果基于ServerSuperIO服務接口的開發具備資料轉發和控制能力,那麼在物聯網建設中将具備資料的無限級聯傳遞與控制能力,使用一套架構形成一套解決方案。示意圖如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuYGOykjMyQjN0kjZldTYiBTOkZjMxcTY1QTZxQ2MmNWMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
12.2 裝置連結器
IRunDevice裝置驅動接口繼承了服務的IServiceConnectorDevice接口,裝置驅動會實作RunServiceConnector接口函數,代表可以接收或運作來自服務執行個體傳遞過來的資料資訊。代碼定義如下:
public interface IServiceConnectorDevice
{
/// <summary>
/// 支行裝置連接配接器
/// </summary>
/// <param name="fromService"></param>
/// <param name="toDevice"></param>
/// <returns></returns>
object RunServiceConnector(IFromService fromService, IServiceToDevice toDevice);
}
12.3 服務連結器
IService接口繼承自IServiceConnector服務連結器,代表服務具備兩大職能:1、向裝置驅動發送指令或資訊。2、接收裝置驅動處理指令或資訊的結果。代碼如下:
public interface IServiceConnector
{
/// <summary>
/// 裝置連接配接器回調函數,在這裡寫回調的處理結果
/// </summary>
/// <param name="obj"></param>
void ServiceConnectorCallback(object obj);
/// <summary>
/// 如果執行方出現異常,則傳回給這個函數結果
/// </summary>
/// <param name="ex"></param>
void ServiceConnectorCallbackError(Exception ex);
/// <summary>
/// 連接配接器事件,發起端
/// </summary>
event ServiceConnectorHandler ServiceConnector;
/// <summary>
/// 确發事件接口
/// </summary>
/// <param name="fromService"></param>
/// <param name="toDevice"></param>
void OnServiceConnector(IFromService fromService, IServiceToDevice toDevice);
}
12.4 場景假設
裝置驅動實時采集傳感器的資料資訊,然後通過OnDeviceObjectChanged事件接口把資料資訊傳遞給服務執行個體UpdateDevice接口函數,然後進行資料的緩存。開啟服務線程,連接配接雲端服務并且定時上傳傳感器的資料資訊。雲端服務下發控制指令command:control:1(注:指令控制1号編碼裝置),然後裝置驅動把指令下發給傳感器,最終把結果傳回給服務執行個體。
12.5 裝置驅動開發及注意事項
1.給服務執行個體傳遞資料資訊,通過OnDeviceObjectChanged事件。代碼如下:
List<string> list = new List<string>();
list.Add(_devicePara.DeviceCode);
list.Add(_devicePara.DeviceName);
list.Add(_deviceDyn.Dyn.Flow.ToString());
list.Add(_deviceDyn.Dyn.Signal.ToString());
OnDeviceObjectChanged(list.ToArray());
2.接收服務執行個體傳遞的指令和資訊。代碼如下:
public override object RunServiceConnector(IFromService fromService, IServiceToDevice toDevice)
{
Console.WriteLine(this.DeviceParameter.DeviceName+",接收到雲端指令:"+toDevice.Text);
return this.DeviceParameter.DeviceName+",執行完成";
}
12.6 服務執行個體開發及注意事項
服務執行個體主要的職能是:緩存資料、連接配接雲端服務并定時發送資料、接收雲端指令資訊并傳遞給裝置驅動、接收驅動執行指令資訊的結果。
- 緩存資料,代碼如下:
public override void UpdateDevice(string devCode, object obj)
{
lock (_SyncObject)
{
if (obj != null)
{
if (obj is string[])
{
string[] arr = (string[])obj;
//OnServiceLog(String.Format("服務:{0} 接收到'{1}'的資料>>{2},{3}", ServiceName, arr[1], arr[2], arr[3]));
if (arr.Length >= 2)
{
if (this._Cache.ContainsKey(devCode)) //判斷ID
{
this._Cache[devCode] = arr;
}
else
{
this._Cache.Add(devCode, arr);
}
}
}
}
}
}
2.連接配接雲端服務并定時發送資料,代碼如下:
private void Target_Service()
{
while (_IsRun)
{
try
{
if (_tcpClient != null)
{
lock (_SyncObject)
{
string content = String.Empty;
foreach (KeyValuePair<string, string[]> kv in _Cache)
{
content += String.Join(",", kv.Value) + Environment.NewLine;
}
if (!String.IsNullOrEmpty(content))
{
byte[] data = System.Text.Encoding.ASCII.GetBytes(content);
this.OnSend(data);
}
}
}
else
{
this.ConnectServer();
}
}
catch (SocketException ex)
{
this.CloseSocket();
OnServiceLog(ex.Message);
}
catch (Exception ex)
{
OnServiceLog(ex.Message);
}
finally
{
System.Threading.Thread.Sleep(2000);
}
}
}
3.接收雲端指令資訊并傳遞給裝置驅動
private void ReceiveCallback(IAsyncResult ar)
{
TcpClient socket = (TcpClient)ar.AsyncState;
try
{
if (socket != null)
{
int read = socket.Client.EndReceive(ar);
if (read > 0)
{
//處理資料.....................通知裝置
string text = System.Text.Encoding.ASCII.GetString(_Buffer, 0, read);
OnServiceConnector(new FromService(this.ServiceName,this.ServiceKey),new ServiceToDevice("1",text,null,null) );
OnReceive();
}
else
{
this.CloseSocket();
}
}
}
catch (SocketException ex)
{
this.CloseSocket();
this.OnServiceLog(ex.Message);
}
catch (Exception ex)
{
this.OnServiceLog(ex.Message);
}
}
4.接收驅動執行指令資訊的結果
public override void ServiceConnectorCallback(object obj)
{
OnServiceLog(obj.ToString());
OnServiceLog("裝置已經處理完成指令");
}
12.7 宿主程式服務執行個體配置注意事項
static void Main(string[] args)
{
DeviceSelfDriver dev2 = new DeviceSelfDriver();
dev2.DeviceParameter.DeviceName = "網絡裝置";
dev2.DeviceParameter.DeviceAddr = 1;
dev2.DeviceParameter.DeviceID = "1";
dev2.DeviceDynamic.DeviceID = "1";
dev2.DeviceParameter.DeviceCode = "1";
dev2.DeviceParameter.NET.RemoteIP = "127.0.0.1";
dev2.DeviceParameter.NET.RemotePort = 9600;
dev2.CommunicateType = CommunicateType.NET;
dev2.Initialize("1");
IServer server = new ServerManager().CreateServer(new ServerConfig()
{
ServerName = "服務1",
ComReadTimeout = 1000,
ComWriteTimeout = 1000,
NetReceiveTimeout = 1000,
NetSendTimeout = 1000,
ControlMode = ControlMode.Self,
SocketMode = SocketMode.Tcp,
StartReceiveDataFliter = true,
ClearSocketSession = false,
StartCheckPackageLength = true,
CheckSameSocketSession = false,
DeliveryMode = DeliveryMode.DeviceCode,
});
server.AddDeviceCompleted += server_AddDeviceCompleted;
server.DeleteDeviceCompleted+=server_DeleteDeviceCompleted;
server.Start();
server.AddDevice(dev2);
TestService.Service service=new TestService.Service();
service.IsAutoStart = true;
server.AddService(service);
while ("exit" == Console.ReadLine())
{
server.Stop();
}
}
12.8 運作效果
1.圖檔
2.視訊
1.
[連載]《C#通訊(序列槽和網絡)架構的設計與實作》2.[
開源]C#跨平台物聯網通訊架構ServerSuperIO(SSIO)介紹2.
應用SuperIO(SIO)和開源跨平台物聯網架構ServerSuperIO(SSIO)建構系統的整體方案3.
C#工業物聯網和內建系統解決方案的技術路線(資料源、資料采集、資料上傳與接收、ActiveMQ、Mongodb、WebApi、手機App)5.ServerSuperIO開源位址:
https://github.com/wxzz/ServerSuperIO物聯網&內建技術(.NET) QQ群:54256083