天天看點

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝

最近,物聯網的概念比較熱門,一大批廠商搶着占領物聯網的高低,包括有華為物聯網、阿裡雲物聯網、騰訊物聯網、AWS物聯網等等,無法一一列舉,一般物聯網包含裝置側開發、平台側開發、應用側開發,三個部分構成了線上線下的完整連接配接,和我們正常的微信應用、釘釘應用等不同,物聯網的終端是由各種各樣的裝置組合而成,這些裝置通過各種不同的協定(如CoAP,LWM2M、MQTT)連接配接到IOT的平台,而且這些裝置是低能耗的裝置,可以實時的發送資料上來,也可以接受來自IOT平台下發的各種操作指令。本篇随筆主要介紹基于華為物聯網IOT的應用開發,實作對.net SDK的封裝,友善後期進行應用內建使用。

最近,物聯網的概念比較熱門,一大批廠商搶着占領物聯網的高低,包括有華為物聯網、阿裡雲物聯網、騰訊物聯網、AWS物聯網等等,無法一一列舉,一般物聯網包含裝置側開發、平台側開發、應用側開發,三個部分構成了線上線下的完整連接配接,和我們正常的微信應用、釘釘應用等不同,物聯網的終端是由各種各樣的裝置組合而成,這些裝置通過各種不同的協定(如CoAP,LWM2M、MQTT)連接配接到IOT的平台,而且這些裝置是低能耗的裝置,可以實時的發送資料上來,也可以接受來自IOT平台下發的各種操作指令。本篇随筆主要介紹基于華為物聯網IOT的應用開發,實作對.net SDK的封裝,友善後期進行應用內建使用。

1、物聯網的相關介紹

物聯網其實有點類似我們以前做的一些行業裝置的接入,不過它相對比較通用化一些,可以連接配接各種各樣的類型裝置,而且更加安全、低能耗等,我們以前接入很多裝置,可能需要走TCP/UDP協定,然後在背景伺服器有一個對這些裝置管理的一個Socket伺服器,不過和物聯網對比,這些都被徹底改造過了,以便适應更多的 應用場景,更簡化的開發,以及支援更強大的功能吧。

物聯網目前可以針對一些傳感器采集一些特定的參數,如光感、溫度、濕度、壓力、電壓、電流等正常的資訊,也可以擴充實作語音、圖像、視訊等方面的采集處理,如經典的智慧路燈應用場景。

下面是其中的一個應用的架構設計,主要就是針對這些裝置管理,物聯網還提供了很多完善的應用API接口,使得我們可以更加簡化對裝置的管理(不用架設Socket服務),更加友善的通過API擷取相應的資訊,節省更多的維護成本。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

物聯網平台支援海量裝置連接配接上雲,裝置與雲端可以實作穩定可靠地雙向通信。

  • 提供裝置端SDK、驅動、軟體包等幫助不同裝置、網關輕松接入物聯網雲。
  • 提供2G/ 3G /4G、NB-IoT、LoRa、WiFi等不同網絡裝置接入方案,解決企業異構網絡裝置接入管理痛點。
  • 提供MQTT、CoAP、HTTP/S等多種協定的裝置端SDK,既滿足長連接配接的實時性需求,也滿足短連接配接的低功耗需求。
  • 開源多種平台裝置端代碼,提供跨平台移植指導,賦能企業基于多種平台做裝置接入。

一般的物聯網平台,都會包括産品管理、裝置管理、裝置組管理、規則引擎管理、消息推送和消息訂閱、任務管理、裝置更新等等,不同的物聯網雲平台有所不同。

物聯網的幾個相關的協定:

MQTT(Message Queue Telemetry Transport)

MQTT是一個物聯網傳輸協定,被設計用于輕量級的釋出/訂閱式消息傳輸,旨在為低帶寬和不穩定的網絡環境中的物聯網裝置提供可靠的網絡服務。

MQTTS指MQTT+SSL/TLS,在MQTTS中使用SSL/TLS協定進行加密傳輸。

CoAP(Constrained Application Protocol)

受限制的應用協定(CoAP)是一種軟體協定,旨在使非常簡單的電子裝置能夠在網際網路上進行互動式通信。

CoAPS指CoAP over DTLS,在CoAPS中使用DTLS協定進行加密傳輸。

LWM2M(lightweight Machine to Machine)

LWM2M是由OMA(Open Mobile Alliance)定義的物聯網協定,主要使用在資源受限(包括存儲、功耗等)的NB-IoT終端

2、應用側開發接口

應用側的開發接口一般雲平台都會提供不同平台的SDK,如阿裡雲開源提供Java SDK/C# SDK等;而華為則提供了Java、PHP等SDK,沒有包含.net 的SDK。

阿裡物聯網雲的應用側API接口包括:

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

 華為物聯網雲的應用側API接口包括:

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰
基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

 本篇主要介紹最基礎的物聯網SDK的包裝,以友善後續的應用開發內建。本篇随筆也主要是基于華為應用側API的封裝,使用C#語言實作對.net SDK的全部封裝處理。

 針對上面的接口分類,我們定義不同的接口類來處理它們。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

基本上所有API通路都先需要通過鑒權接口擷取通路的token,鑒權接口定義如下所示。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

而且華為的API接口,需要使用X509證書處理的,我們可以通過在官網下載下傳對應的X509證書進行內建測試API。

為了實作對API進行的.net SDK封裝,我們定義一些系統常見變量,友善在接口中使用。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

 根據鑒權傳回的結果,我們定義一個對應的實體類來存儲這些屬性資訊,如下所示。

/// <summary>
    /// 鑒權結果
    /// </summary>
    public class AuthenticationResult : BaseJsonResult
    {
        /// <summary>
        /// 申請權限範圍,即accessToken所能通路物聯網平台資源的範圍,參數值固定為default。
        /// </summary>
        public string scope { get; set; }

        /// <summary>
        /// accessToken的類型,參數值固定為Bearer 。
        /// </summary>
        public string tokenType { get; set; }

        /// <summary>
        /// accessToken的有效時間,參數值固定為3600秒
        /// </summary>
        public int expiresIn { get; set; }

        /// <summary>
        /// 鑒權參數,通路物聯網平台API接口的憑證。
        /// </summary>
        public string accessToken { get; set; }

        /// <summary>
        /// 鑒權參數,有效時間為1個月,用于“重新整理Token”接口。
        /// 當accessToken即将過期時,可通過“重新整理Token”接口來擷取新的accessToken。
        /// </summary>
        public string refreshToken { get; set; }
    }      

然後根據鑒權定義,我們實作對這個接口的封裝處理。

/// <summary>
    /// IOT鑒權接口實作
    /// </summary>
    public class AuthenticationApi : IAuthenticationApi
    {
        /// <summary>
        /// 使用者鑒權
        /// 應用伺服器首次通路物聯網平台的開放API時,需調用此接口完成接入認證;
        /// 應用伺服器在物聯網平台的認證過期後,需調用此接口重新進行認證,才能繼續通路物聯網平台的開放API。
        /// </summary>
        public AuthenticationResult Authentication()
        {
            string postData = string.Format("appId={0}&secret={1}", Constants.AppId, Constants.Secret);
            var url = Constants.AppBaseUrl + "/iocm/app/sec/v1.1.0/login";//名稱大小寫不能錯

            HttpHelper helper = new HttpHelper();
            helper.ContentType = "application/x-www-form-urlencoded";
            helper.ClientCertificates = new X509CertificateCollection() { new X509Certificate2(Constants.CertFilePath, Constants.CertPassword) };

            string content = helper.GetHtml(url, postData, true);
            var result = JsonConvert.DeserializeObject<AuthenticationResult>(content);
            return result;
        }      

對于Token的重新整理操作,封裝也是類似操作

/// <summary>
        /// 重新整理token。
        /// 應用伺服器通過鑒權接口擷取到的accessToken是有有效時間的,在accessToken快過期時,
        /// 應用伺服器通過調用此接口,擷取新的accessToken。
        /// </summary>
        /// <param name="refreshToken">
        /// 重新整理token,用來擷取一個新的accessToken。refreshToken在調用鑒權接口或重新整理token接口時獲得。
        /// </param>
        /// <returns></returns>
        public AuthenticationResult RefreshToken(string refreshToken)
        {
            string postData = new
            {
                appId = Constants.AppId,
                secret = Constants.Secret,
                refreshToken = refreshToken
            }.ToJson();
            var url = Constants.AppBaseUrl + "/iocm/app/sec/v1.1.0/refreshToken";//名稱大小寫不能錯

            var result = WeJsonHelper<AuthenticationResult>.ConvertJson(url, postData);
            return result;
        }      

上面有些是為了友善操作,定義了一些公用類庫,以減少代碼的重複。

一般除了鑒權外的所有的API,它們處理方式都類似的,都是以 application/json 格式進行互動,使用POST、PUT、GET、Delete操作方式實作對資料的處理。

而且它們都需要有固定的請求頭資訊,我們以裝置注冊為例進行介紹。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

一般我們可以通過一個函數封裝,對接口的頭部請求資訊進行設定,如下所示。

/// <summary>
        /// 通用擷取頭部資訊
        /// </summary>
        /// <param name="accessToken">接口通路密碼</param>
        /// <returns></returns>
        protected NameValueCollection GetHeader(string accessToken)
        {
            var header = new NameValueCollection();
            header.Add(Constants.HEADER_APP_KEY, Constants.AppId);
            header.Add(Constants.HEADER_APP_AUTH, string.Format("Bearer {0}", accessToken));
            return header;
        }      

然後在定義請求的JSON和傳回的JSON對應的實體類對象,封裝對應的API接口即可。

例如,我們注冊裝置的接口封裝如下所示。

/// <summary>
    /// 裝置管理接口實作
    /// </summary>
    public class DeviceApi : BaseCommon, IDeviceApi
    {
        /// <summary>
        /// 注冊裝置(驗證碼方式)。
        /// 在裝置接入物聯網平台前,應用伺服器需要調用此接口在物聯網平台注冊裝置,并設定裝置的唯一辨別(如IMEI)。
        /// 在裝置接入物聯網平台時攜帶裝置唯一辨別,完成裝置的接入認證。
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        public RegDeviceResult RegisterDevice(string accessToken, RegDeviceJson info)
        {
            var header = GetHeader(accessToken);

            string postData = info.ToJson();
            var url = Constants.AppBaseUrl + "/iocm/app/reg/v1.1.0/deviceCredentials";//名稱大小寫不能錯
            url += string.Format("?appId={0}", Constants.AppId);

            var result = WeJsonHelper<RegDeviceResult>.ConvertJson(url, postData, header);
            return result;
        }
......      

這裡請求的資訊是 RegDeviceJson , 傳回資訊的類是RegDeviceResult 。我們依照API定義,實作對應的處理即可。

為了友善處理,我們可以把這些對應裝置的實體類定義在一個檔案裡面,如DeviceJson.cs裡面,如下所示,這樣非常友善我們管理。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

 其他業務範疇的Api也是如此封裝,不在一一贅述。

我們測試的時候,可以建立一個單獨的Winform項目進行接口功能的測試,也可以自己編寫單元測試代碼進行測試,根據自己熟練程度選擇吧。

例如鑒權接口測試代碼如下所示,我們可以看看輸出進行判斷是否正常工作。

private void btnLogin_Click(object sender, EventArgs e)
        {
            var result = basicApi.Authentication();
            Console.WriteLine(result != null ? "accessToken:" + result.ToJson() : "擷取結果出錯");

            if (result != null)
            {
                var refreshResult = basicApi.RefreshToken(result.refreshToken);

                Console.WriteLine(refreshResult != null ? "accessToken:" + refreshResult.ToJson() : "擷取結果出錯");
                this.accessToken = refreshResult.accessToken;//記錄待用
            }
        }      

裝置注冊的功能測試如下所示。

private void btnRegDevice_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(accessToken))
            {
                MessageUtil.ShowTips("請先鑒權擷取AccessToken");
                return;
            }

            var deviceApi = new DeviceApi();
            var regDeviceInfo = new RegDeviceJson()
            {
                endUserId = "64bf5869-b271-4007-8db8-fab185e19c10",
                nodeId = "64bf5869-b271-4007-8db8-fab185e19c10",
                psk = "12345678",
                timeout = 0,
                verifyCode = "",
                deviceInfo = new DeviceJson()
                {
                    deviceType = "Smoke",
                    manufacturerId = "49ac78c99f3e453598c155870efe8bfc",
                    manufacturerName = "iqidi",
                    //與manufacturerId、manufacturerName、deviceType、model和protocolType系列參數二選一
                    //productId = "5d9bf49b6a018f02d04cae28",
                    model = "1001",
                    name = "NBSimulator",
                    imsi = "fafafasfasf",
                    mac = "testetst",
                    isSecurity = true.ToString().ToUpper(),
                    protocolType = "LWM2M",
                }
            };

            var regResult = deviceApi.RegisterDevice(accessToken, regDeviceInfo);
            Console.WriteLine(regResult != null ? regResult.ToJson() : "no regResult");
        }      

另外對于事件的通知,我們一般是在應用端被動的進行相應的處理,是以需要對它們的消息進行轉換和處理。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

 針對以上的消息通知,我們需要定義對應的消息類型,然後進行判斷處理。

我們另起一個項目,然後定義對應給的事件接收處理,如下所示是一個統一的入口處理。

基于華為物聯網IOT的應用開發 --- 基于.net 的SDK封裝 - 伍華聰

有了一個總入口,我們把對應通知的資訊轉換為對應的實體後,就可以進行記錄或者響應的處理了。

在後面我們接着開發應用功能的時候,這些對應的接口API就可以內建整合在我們的系統中了。

 以上就是對于華為物聯網IOT平台應用側的API封裝處理的思路, 供大家參考交流。