當前位置: 妍妍網 > 碼農

.NET 開源智慧家居之小米米家原生SDK【MiHome.Net】1.0.0釋出

2024-04-28碼農

智慧家居簡直剛需,在上一篇文章 中有靚仔提到,沒有蘋果裝置,有一說一,蘋果手機很貴,並且原生支持蘋果HomeKit的智慧家居裝置也很貴,同時沒幾款可選的,還是米家的智慧家居裝置價效比更高同時品類更豐富,作為一個資深米粉,手機從紅米note到小米6,小米8,再到小米10

接著如今全屋智慧家居基本都是米家的,我對小米可謂愛的深沈,歡迎大家選購智慧家居裝置的時候優先選擇小米,因為他真的很棒(手動狗頭,雷軍義父,請打錢謝謝)。

但米家也有缺點,那就是米家並沒有提供c#的sdk讓我們能原生呼叫api,只能透過米家app操控裝置,沒有api這可玩性就太低了

神說:要有光,於是我今天便帶著[MiHome.Net]來了,這個庫主要參考了python的【python-miio】和【hass-xiaomi-miot】這2個計畫。

有了原生api就有了無限可能,大家可以盡情的發揮想象力去搞事了,接下來,我將介紹他的用法。

米家中的一些基本概念

米家中每一個智慧家居裝置稱為一個裝置(Device),每個裝置擁有多個服務(Services),每個服務又有多個內容(Property)以及(0-N)個方法(Action,大家把方法理解為封裝好的函式即可,

我們可以直接呼叫方法來完成一些操作),所有裝置都有裝置資訊服務,這個服務裏包含了多個基本內容,包括裝置型號,裝置制造商,裝置序列號等,並且裝置根據功能還有另外一些獨有的服務,我們以一個開關為例,開關本身就是一個裝置,他擁有一個服務叫Switch,這個服務下面,有一個內容叫Switch Status,也就是開關,我們給這個內容賦值true,就代表開,賦值false,就代表關,同時米家裝置支持2種操控方式,基於雲端和基於本地,

這兩者的主要區別就在於雲端需要裝置以及手機有互聯網連線,使用者的操作指令是先發送到小米伺服器,然後小米伺服器下達指令給到智慧裝置,而基於本地則不同,他是直接透過ip和token,將指令發送給智慧裝置,這個過程,只需要區域網路即可。

所有米家智慧家居裝置都支持雲端操作,但不是所有裝置都支持本地操作,主要看裝置情況。

MiHome.Net存在的意義

使用本依賴包,使用者可以透過雲端或者原生的方式用c#原生api來操作米家智慧家居裝置。

Getting Started

1、Nuget

接下來我將演示如何使用【MiHome.Net】,你可以執行以下命令在你的計畫中安裝 MiHome.Net 。

PM> Install-Package MiHome.Net

2、支持框架

.NET 6,.NET 8

3、api使用講解

本庫基於依賴註入,首先新建一個控制台套用,引入MiHome.Net的nuget包,接著添加小米米家的驅動服務,需要配置米家帳號和密碼,程式碼如下:

var hostBuilder = Host.CreateDefaultBuilder();
//添加小米米家的驅動服務,需要小米帳號和密碼
 hostBuilder.ConfigureServices(it => it.AddMiHomeDriver(x =>
 {
x.UserName = "<這裏填寫米家帳號>";
x.Password = "<這裏填寫米家米家>";
 }));
var host = hostBuilder.Build();
var miHomeDriver = host.Services.GetService<IMiHomeDriver>();

獲取到米家驅動服務以後,我們首先透過雲端的方式呼叫介面,列出家庭裏所有的智慧家居裝置,接著透過米家app裏自己設定的裝置名稱找出自己想要操作的智慧家居裝置,我這裏演示的是一個【米家智慧插座2】,

我將3D打印出來的月球燈連到了這個插座上,並在米家app裏將這個插座命名為月球燈,這樣就將月球燈接入了智慧家居。

繼續講解api,接下來透過裝置型號獲取裝置規格,這一步的目的,主要是了解我們要操作的智慧家居裝置都有哪些服務,哪些方法,哪些內容,並獲得它們的id,因為我們操作智慧家居需要用到裝置id(即did),服務id(即siid),內容id(即piid),方法id(即aiid),程式碼如下:

//列出家庭裏所有的智慧家居裝置
var deviceList = await miHomeDriver.Cloud.GetDeviceListAsync();
//透過米家app裏自己設定的智慧家居名稱找出自己想要操作的智慧家居裝置
var moonLight = deviceList.FirstOrDefault(it => it.Name == "月球燈");
//透過裝置型號獲取裝置規格
var result = await miHomeDriver.Cloud.GetDeviceSpec(moonLight.Model);

我這裏將獲取到的規格結果截圖出來給大家講解一下

從上圖中可以看到,這個裝置總共有8個服務,逐一點開後我發現我只需要了解switch服務(即開關服務)即可,它的iid為2(即siid為2),同時這個服務下有3個內容,逐一點開檢視後我發現,我只需要了解Switch Status內容即可,他的iid為1(即piid為1),同時這個內容值的格式(Format)是bool型別,即這個內容值只能為true或者false,接下來我將演示如何獲取開關狀態,程式碼如下:

//透過本地方式獲取內容值
var r1 = await miHomeDriver.Local.GetPropertyAsync(moonLight.LocalIp, moonLight.Token, new GetPropertyPayload()
{
Siid = 2,
Piid = 1
});
//透過雲端方式獲取內容值
var r7 = await miHomeDriver.Cloud.GetPropertyAsync(new GetPropertyDto()
{
Did = moonLight.Did,
Siid = 2,
Piid = 1
});

如上程式碼所示,支持本地以及雲端的方式獲取內容值,本地獲取的方式需要傳入智慧家居裝置的ip,智慧家居裝置的token,這兩者都是之前透過雲端裝置介面GetDeviceListAsync返回的,以及參數siid和piid,這兩者是我們之前透過檢視裝置規格獲得的,透過雲端的方式獲取內容值,則額外需要did(即裝置id),它同樣是透過雲端裝置介面GetDeviceListAsync返回的,本地或雲端呼叫後我們就獲取到了開關當前的狀態,呼叫結果如下圖,value值為false,即代表開關當前處於關閉狀態

接下來我將演示如何設定開關狀態,程式碼如下:

//透過本地方式設定內容值
var r2 = await miHomeDriver.Local.SetPropertyAsync(moonLight.LocalIp, moonLight.Token, new SetPropertyPayload()
{
Siid = 2,
Piid = 1,
Value = true
});
//透過雲端方式設定內容值
var r8 = await miHomeDriver.Cloud.SetPropertyAsync(new SetPropertyDto()
{
Did = moonLight.Did,
Siid = 2,
Piid = 1,
Value = true
});

如上程式碼所示,支持本地以及雲端的方式設定內容值,參數和獲取內容值差不多,只是多了一個value參數,代表我們要設定的值,這雷根據裝置規格中format為bool,我們將它設定為true,即代表開。同時這些操作也支持批次獲取和批次設定,程式碼如下

//透過本地方式批次獲取內容值
var r3 = await miHomeDriver.Local.GetPropertiesAsync(moonLight.LocalIp, moonLight.Token, new List<GetPropertyPayload>(){new GetPropertyPayload()
{
Siid = 2,
Piid = 1
}});
//透過雲端方式批次獲取內容值
var r5 = await miHomeDriver.Cloud.GetPropertiesAsync(new List<GetPropertyDto>()
{
new GetPropertyDto()
{
Did = moonLight.Did,
Siid = 2,
Piid = 1
}
});
//透過本地方式批次設定內容值
var r4 = await miHomeDriver.Local.SetPropertiesAsync(moonLight.LocalIp, moonLight.Token, new List<SetPropertyPayload>(){new SetPropertyPayload()
{
Siid = 2,
Piid = 1,
Value =true
}});

//透過雲端方式批次設定內容值
var r6 = await miHomeDriver.Cloud.SetPropertiesAsync(new List<SetPropertyDto>()
{
new SetPropertyDto()
{
Did = moonLight.Did,
Siid = 2,
Piid = 1,
Value = true
}
});


接下來我給大家演示如何透過雲端或者原生的方式呼叫裝置服務裏的方法,因為米家智慧插座2沒啥方法可以呼叫,所以我將使用【Gosund智慧排插CP5 Pro】和【小愛音箱Play增強版】來給大家演示呼叫,先來【Gosund智慧排插CP5 Pro】,這個排插長這樣

他上面的4個插座都支持獨立控制,我個人非常喜歡,強烈推薦(手動狗頭,廠家打錢!),接下來我將演示呼叫4個插座其中插座3的方法來控制插座3的開關,

和上面一樣,我們首先查規格,程式碼如下

var cp5pro = deviceList.FirstOrDefault(it => it.Name == "Gosund智慧排插CP5 Pro");
var result3 = await miHomeDriver.Cloud.GetDeviceSpec(cp5pro.Model);

獲得的規格如下圖

如上圖可以看出,插座3有一個方法(即action)叫toggle,這個方法主要就是改變插座3當前的狀態,如果原來是關,呼叫即為開,

如果原來是開,呼叫即為關,同時iid為1(即aiid為1),服務id為5(即siid為5),入參in為空陣列,即不需要傳入參數,out也為空陣列,表示呼叫沒有返回,不多說了,上程式碼:

//使用雲端方式呼叫Gosund智慧排插CP5 Pro中4個開關中第3個開關的toggle方法
var r11 = await miHomeDriver.Cloud.CallActionAsync(new CallActionInputDto()
{
Did = cp5pro.Did,
Aiid = 1,
Siid = 5,
In = new List<string>() { }
});
//使用本地方式呼叫Gosund智慧排插CP5 Pro中4個開關中第3個開關的toggle方法
var r10 = await miHomeDriver.Local.CallActionAsync(cp5pro.LocalIp, cp5pro.Token, new CallActionPayload()
{
Siid = 5,
Aiid = 1,
In = new List<string>() { }
});

如上程式碼所示,和設定/獲取內容不同,呼叫方法是透過服務id(即siid)和方法id(即aiid)以及入參in來實作的。

接下來演示呼叫【小愛音箱Play增強版】的服務方法來播放自訂文本,先上圖

和上面一樣,我們首先查規格,程式碼如下

var xiaoAi = deviceList.FirstOrDefault(it => it.Name == "小愛音箱Play增強版");
var result2 = await miHomeDriver.Cloud.GetDeviceSpec(xiaoAi.Model);

獲得的規格如下圖

如上圖可以看出,小愛音箱有一個方法(即action)叫Play Text,這個方法用來播放自訂語音,同時iid為3(即aiid為3),服務id為5(即siid為5),入參in為陣列,需要傳入一個參數,即我們的自訂文本,out為空陣列,表示呼叫沒有返回,同時這個方法只支持雲端呼叫,不支持本地呼叫,為啥我知道?

因為我試過了,本地方法沒反應,這個應該是需要伺服器把文本轉為語音,再回傳到小愛音箱來播放,不多說了,上程式碼:

//使用小愛音箱Play增強版播放我們的自訂文字
var r9 = await miHomeDriver.Cloud.CallActionAsync(new CallActionInputDto()
 {
Did = xiaoAi.Did,
Aiid = 3,
Siid = 5,
In = new List<string>() { "門前大橋下,遊過一群鴨" }
 });

開源地址

本計畫基於MIT協定開源

https://github.com/TripleView/MiHome.Net

同時感謝以下計畫

1、python-miio:https://github.com/rytilahti/python-miio

2、hass-xiaomi-miot:https://github.com/al-one/hass-xiaomi-miot

總結

如果各位靚仔覺得這個計畫不錯,歡迎一鍵三連(推薦,star,關註),有了【MiHome.Net】和【Homekit.Net】,想必各位靚仔應該能自己寫程式將米家智慧家居裝置橋接到HomeKit生態裏去了,反正我自己已經用了很久了,然後希望大家不要過於頻繁的進行雲端呼叫,以免對米家伺服器造成不良影響。

轉自: 三合視角

連結:cnblogs.com/hezp/p/18156704

- EOF -

推薦閱讀 點選標題可跳轉

看完本文有收獲?請轉發分享給更多人

推薦關註「DotNet」,提升.Net技能

點贊和在看就是最大的支持❤️