學(xué)習(xí)使用homeBridge開(kāi)發(fā)自己的插件

公司大佬叫我研究下HomeKit,準(zhǔn)備和公司的產(chǎn)品對(duì)接上萧锉,正常流程肯定不行(需要蘋(píng)果認(rèn)證才能),所有就要學(xué)習(xí)homeBridge這個(gè)神來(lái)之筆。

homeBridge是一個(gè)大神開(kāi)發(fā)了神器茴丰,使用nodejs平臺(tái),破解了蘋(píng)果的HomeKit的那個(gè)什么協(xié)議天吓,可以將自己的設(shè)備添加到蘋(píng)果app(家庭)上面贿肩,然后實(shí)現(xiàn)控制自己的設(shè)備。像小米的很早就實(shí)現(xiàn)了龄寞,俺們公司小不能比汰规。

第一步:了解并下載homeBridge

https://github.com/nfarina/homebridge

首先你需要打開(kāi)下面的鏈接,然后好好的看一遍或者幾遍
https://github.com/nfarina/homebridge
并下載homeBridge

第二步:可能遇到的問(wèn)題

問(wèn)題1:
$ homebridge
No plugins found. See the README for information on installing plugins.

沒(méi)有找到插件物邑,第一步的網(wǎng)頁(yè)有解釋?zhuān)阈枰螺d一個(gè)插件溜哮,或者像我一樣自己開(kāi)發(fā)一個(gè),當(dāng)然我開(kāi)發(fā)的只針對(duì)本公司的設(shè)備

問(wèn)題2:
$ homebridge
Couldn't find a config.json file [snip]

沒(méi)有找到config.json文件色解,你需要?jiǎng)?chuàng)建一個(gè)config.json文件茂嗓,然后將這個(gè)文件放到. homeBridge里面
這時(shí)候你可能迷糊了,. homeBridge在哪科阎?
為了詳細(xì)述吸,我要開(kāi)始圖文解析了:

打開(kāi)Finder


image.png

在上圖kk文件下,你的就是mac名稱(chēng)锣笨,同時(shí)按下 command+shift+. 顯示隱藏文件蝌矛,就可以看到. homeBridge了

image.png

問(wèn)題3:config.json怎么寫(xiě)

直接復(fù)制吧然后放到. homeBridge下

{
    "bridge": {
    "name": "Homebridge",
    "username": "CC:22:3D:E3:CE:30",
    "port": 51825,
    "pin": "111-11-122"
    },
    
    "description": "This is an example configuration file with pilight plugin.",

    
  "platforms": [
    {
      "platform": "SamplePlatform",
      "sid": ["6409802da3ca"],
      "password": ["1234567890123456"]
    }]
}
復(fù)制到這兒
platform:為平臺(tái)的名稱(chēng),后面需要注冊(cè)與這兒的名稱(chēng)保證一樣票唆。

第三步:開(kāi)始創(chuàng)建自己的插件

如果你已經(jīng)完成前兩步朴读,執(zhí)行命令會(huì)出現(xiàn)錯(cuò)誤


image.png

剛才在config.json寫(xiě)的 "platform": "SamplePlatform"平臺(tái)下未注冊(cè)任何插件,這時(shí)候你已經(jīng)配置好所有前提條件走趋,剩下的就是最后一步衅金,創(chuàng)建一個(gè)插件

1:創(chuàng)建index.js

進(jìn)到homeBridge所在的目錄:/usr/local/lib/node_modules
然后創(chuàng)建一個(gè)文件夾homebridge-sampleplatform

image.png

在文件下創(chuàng)建index.js文件

//deviceSwitch里是操作設(shè)備的命令
var kkDeviceApi = require(__dirname + '/deviceSwitch');
var Accessory, Service, Characteristic, UUIDGen;
var that;  //指向SamplePlatform 初始化內(nèi)部this

module.exports = function(homebridge) {
  console.log("homebridge API version: " + homebridge.version);
  // Accessory must be created from PlatformAccessory Constructor
  Accessory = homebridge.platformAccessory;

  // Service and Characteristic are from hap-nodejs
  Service = homebridge.hap.Service;
  Characteristic = homebridge.hap.Characteristic;
  UUIDGen = homebridge.hap.uuid;
  
  // For platform plugin to be considered as dynamic platform plugin,
  // registerPlatform(pluginName, platformName, constructor, dynamic), dynamic must be true
  homebridge.registerPlatform("homebridge-sampleplatform", "SamplePlatform", SamplePlatform, true);
};

// Platform constructor
// config may be null
// api may be null if launched from old homebridge version
function SamplePlatform(log, config, api) {
  log("SamplePlatform Init");
  this.log = log;
  this.config = config;
  this.kkAccessories = [];
  that = this;
  console.log('this指向1=',this);
  if (api) {
      // Save the API object as plugin needs to register new accessory via this object
      this.api = api;
      // Listen to event "didFinishLaunching", this means homebridge already finished loading cached accessories.
      // Platform Plugin should only register new accessory that doesn't exist in homebridge after this event.
      // Or start discover new accessories.
      this.api.on('didFinishLaunching', function() {
          this.log("DidFinishLaunching");
          kkDeviceApi.DeviceControl.DeviceDiscovery();
      }.bind(this));
  }
}
/*---------------為SamplePlatform添加方法------------*/
SamplePlatform.prototype = {
    //發(fā)現(xiàn)設(shè)備
    onDevice: function (devInfo) {
        console.log('this指向2=',that);
        var that2 = this;   //指向當(dāng)前,回調(diào)函數(shù)需要使用
        console.log('onDevice=',devInfo);
        //判斷設(shè)備類(lèi)型
        var serviceObj = this.decideDevType(devInfo['device_type']);
        if (serviceObj === null) {
            console.log('未知設(shè)備000');
            return;
        }
        var uuid;
        var name;
        var newAccessory = null;
        var devExit = 0;
        var kkService = null;
        for (var index in that.kkAccessories) {
            var obj = that.kkAccessories[index];
            console.log('對(duì)象==', obj);
            if (obj.context.did === devInfo['device_mac']) {
                devExit = 1;
                newAccessory = obj;
                break;
            }
        }
        if (devExit) {
            console.log("已存在設(shè)備cached accessory: " + newAccessory.context.did);
            kkService = newAccessory.getService(serviceObj);
        }else {
            uuid = UUIDGen.generate(devInfo['device_mac']);
            name = devInfo['device_mac'].substring(devInfo['device_mac'].length-6);
            console.log("found dev: " + name);
            newAccessory = new Accessory(name, uuid);
            newAccessory.context.did = devInfo['device_mac'];
            newAccessory.context.model = devInfo['device_type'];
            kkService = new serviceObj(name);
            console.log("新創(chuàng)建設(shè)備newAccessory: " + newAccessory.context.did);
        }
        console.log('服務(wù)=',kkService);
        devInfo.accessory = newAccessory;
        kkService
            .getCharacteristic(Characteristic.On)
            .on('set', function(value, callback) {
                console.log('this指向3=',that2);
                that2.controlDevice(devInfo['device_mac'], "power", value, callback);
            });
            // .value = dev.power;
        if (devExit) {
            if (this.isSwitch(devInfo['device_type'])) {
                this.isSwithcGetCharacteristic(kkService, devInfo);
            }else if (this.isKlight(devInfo['device_type'])) {
                this.isKlightGetCharacteristic(kkService, devInfo);
            }
        }else {
            if (this.isSwitch(devInfo['device_type'])) {
                this.isSwithcAddCharacteristic(kkService, devInfo);
            }else if (this.isKlight(devInfo['device_type'])) {
                this.isKlightAddCharacteristic(kkService, devInfo);
            }
        }
        newAccessory.reachable = true;

        if (!devExit) {
            console.log('注冊(cè)這個(gè)設(shè)備', newAccessory.context.did);
            newAccessory.addService(kkService, name);
            that.kkAccessories.push(newAccessory);
            that.api.registerPlatformAccessories("homebridge-samplePlatform", "SamplePlatform", [newAccessory]);
        }
    },

    configureAccessory: function(accessory) {
        console.log('configureAccessory', accessory.context.did);
        //accessory.updateReachability(false);
        accessory.reachable = true;
        accessory.on('identify', function(paired, callback) {
            console.log("identify ....");
        });
        that.kkAccessories.push(accessory);
    },

    //執(zhí)行命令
    controlDevice: function(did, characteristic, value, callback) {
        console.log('控制設(shè)備=',did);
        var devInfo = kkDeviceApi.DeviceControl.SearchDeviceInfo(did);
        if (devInfo === null) {
            console.log("no device found for did: " + did);
            return;
        }
        switch(characteristic.toLowerCase()) {
            case 'identify':
                console.log("identfy....");
                // dev.setBlink();
                break;
            case 'power':
                console.log('power....');
                kkDeviceApi.DeviceControl.SetSwitch(did, value);
                break;
            case 'hue':
                // dev.setColor(value, dev.sat);
                break;
            case 'brightness':
                // dev.setBright(value);
                break;
            case 'saturation':
                // dev.setColor(dev.hue, value);
                break;
            default:
                break;
        }

        if (callback)
            callback();
    },

    decideDevType: function (devType) {
        if (devType === 'k2' ||
            devType === 'mini_w' ||
            devType === 'k2pro' ||
            devType === 'k2pro' ||
            devType === 'konke_other') {
            return Service.Switch;
        }else {
            return null;
        }
    },

    isSwitch: function (devType) {
        if (devType === 'k2' ||
            devType === 'mini_w' ||
            devType === 'k2pro' ||
            devType === 'k2pro') {
            return 1;
        }
        return 1;
    },

    isKlight: function (devType) {
        if (devType === 'klight') {
            return 1;
        }
        return 0;
    },

    isSwithcGetCharacteristic: function (service, devInfo) {

    },

    isKlightGetCharacteristic: function (lightService, devInfo) {
        var that2 = this;   //指向當(dāng)前,回調(diào)函數(shù)需要使用
        lightService
            .getCharacteristic(Characteristic.Brightness)
            .on('set', function(value, callback) { that2.controlDevice(devInfo['devMac'], "brightness", value, callback);})
        // .value = dev.bright;
        lightService
            .getCharacteristic(Characteristic.Hue)
            .on('set', function(value, callback) { that2.controlDevice(devInfo['devMac'], "hue", value, callback);})
            // .value = dev.hue;
        lightService
            .getCharacteristic(Characteristic.Saturation)
            .on('set', function(value, callback) { that2.controlDevice(devInfo['devMac'], "saturation", value, callback);})
            // .value = dev.sat;
    },

    isSwithcAddCharacteristic: function (service, devInfo) {

    },

    isKlightAddCharacteristic: function (lightService, devInfo) {
        var that2 = this;   //指向當(dāng)前氮唯,回調(diào)函數(shù)需要使用
        lightService
            .addCharacteristic(Characteristic.Brightness)
            .on('set', function(value, callback) { that2.controlDevice(devInfo['devMac'], "brightness", value, callback);})
            // .value = dev.bright;
        lightService
            .addCharacteristic(Characteristic.Hue)
            .on('set', function(value, callback) { that2.controlDevice(devInfo['devMac'], "hue", value, callback);})
            // .value = dev.hue;

        lightService
            .addCharacteristic(Characteristic.Saturation)
            .on('set', function(value, callback) { that2.controlDevice(devInfo['devMac'], "saturation", value, callback);})
            // .value = dev.sat;
    }
};
exports.SamplePlatform = SamplePlatform;

//里面的方法就不解釋了鉴吹,慢慢看,總能看懂的惩琉。deviceSwitch.js是控制設(shè)備的命令豆励,你懂得

2:創(chuàng)建package.json
{
  "name": "homebridge-samplePlatform",
  "version": "0.0.1",
  "description": "Sample Platform plugin for homebridge: https://github.com/nfarina/homebridge",
  "license": "ISC",
  "keywords": [
    "homebridge-plugin"
  ],
  "repository": {
    "type": "git",
    "url": "git://github.com/example/homebridge.git"
  },
  "bugs": {
    "url": "http://github.com/example/homebridge/issues"
  },
  "engines": {
    "node": ">=0.12.0",
    "homebridge": ">=0.2.0"
  }
}
3:在app上添加平臺(tái)
image.png

這時(shí)候會(huì)出現(xiàn)一個(gè)二維碼和pin碼

image.png

手機(jī)打開(kāi)HomeKit添加配件,掃描二維碼或者pin碼瞒渠,生成一個(gè)平臺(tái)

在deviceSwitch.js文件中會(huì)掃描局域網(wǎng)設(shè)備良蒸,然后調(diào)用index.js中的onDevice()方法將設(shè)備添加到平臺(tái)下,app會(huì)自動(dòng)生成一個(gè)開(kāi)關(guān)或者其他類(lèi)型的設(shè)備

5C459791E6B72C4C39C77B1C2B508872.jpg

好了伍玖,先就這樣了......

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嫩痰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子窍箍,更是在濱河造成了極大的恐慌串纺,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件椰棘,死亡現(xiàn)場(chǎng)離奇詭異纺棺,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)邪狞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)祷蝌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人外恕,你說(shuō)我怎么就攤上這事杆逗∠绯幔” “怎么了鳞疲?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蠕蚜。 經(jīng)常有香客問(wèn)我尚洽,道長(zhǎng),這世上最難降的妖魔是什么靶累? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任腺毫,我火速辦了婚禮,結(jié)果婚禮上挣柬,老公的妹妹穿的比我還像新娘潮酒。我一直安慰自己,他們只是感情好邪蛔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布急黎。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪勃教。 梳的紋絲不亂的頭發(fā)上淤击,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音故源,去河邊找鬼污抬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛绳军,可吹牛的內(nèi)容都是我干的印机。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼门驾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼耳贬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起猎唁,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤咒劲,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后诫隅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體腐魂,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年逐纬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛔屹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豁生,死狀恐怖兔毒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甸箱,我是刑警寧澤育叁,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站芍殖,受9級(jí)特大地震影響豪嗽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜豌骏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一龟梦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窃躲,春花似錦计贰、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赎婚。三九已至,卻和暖如春樱溉,著一層夾襖步出監(jiān)牢的瞬間挣输,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工福贞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撩嚼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓挖帘,卻偏偏與公主長(zhǎng)得像完丽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子拇舀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容