boboskit - एक्सेसरीज़, dnssd और WebSocket


इस प्रकार, मैंने प्रबंधित सॉफ़्टवेयर सामान की एक प्रणाली की संरचना का वर्णन किया।


सरलीकृत मॉडल में मुख्य प्रक्रिया ( bobaoskit.worker ) और गौण स्क्रिप्ट ( bobaoskit.sdk और bobaoskit.accessory का उपयोग करके) शामिल हैं। मुख्य प्रक्रिया से कुछ क्षेत्रों को नियंत्रित करने के लिए एक गौण के लिए अनुरोध है। गौण से, बदले में, स्थिति को अद्यतन करने के लिए मुख्य बात का अनुरोध है।


उदाहरण के रूप में एक साधारण रिले लें।


एक आने वाली कमांड के साथ, रिले कभी-कभी विभिन्न कारणों (उपकरण फ्रीज, आदि) के कारण अपनी स्थिति नहीं बदल सकता है। इसके अनुसार, हम टीमों को कितना नहीं भेजेंगे, स्थिति नहीं बदलेगी। और, एक अन्य स्थिति में, तृतीय-पक्ष प्रणाली द्वारा कमांड किए जाने पर रिले अपना राज्य बदल सकता है। इस स्थिति में, इसकी स्थिति बदल जाएगी, एक्सेसरी स्क्रिप्ट स्थिति परिवर्तन के बारे में आने वाली घटना का जवाब दे सकती है और मुख्य प्रक्रिया के लिए अनुरोध भेज सकती है।


प्रेरणा


कई वस्तुओं पर Apple होमकिट लागू करने के बाद, मैंने एंड्रॉइड के समान कुछ ढूंढना शुरू कर दिया, क्योंकि मेरे पास केवल आईओएस उपकरणों से काम करने वाला आईपैड है। मुख्य मानदंड एक स्थानीय नेटवर्क पर काम करने की क्षमता थी, बिना क्लाउड सेवाओं के। इसके अलावा, होमकिट में क्या गायब था, इसकी सीमित जानकारी थी। उदाहरण के लिए, आप थर्मोस्टैट ले सकते हैं। इसका सारा नियंत्रण ऑपरेटिंग मोड (ऑफ, हीटिंग, कूलिंग और ऑटो) और सेट तापमान की पसंद तक कम हो जाता है। सरल बेहतर है, लेकिन, मेरी राय में, हमेशा नहीं। पर्याप्त नैदानिक ​​जानकारी नहीं। उदाहरण के लिए, क्या एयर कंडीशनर, convector, क्या वेंटिलेशन पैरामीटर काम कर रहे हैं। आंतरिक त्रुटि के कारण शायद एयर कंडीशनर काम नहीं कर सकता है। यह देखते हुए कि इस जानकारी पर विचार किया जा सकता है, इसके कार्यान्वयन को लिखने का निर्णय लिया गया।


कोई व्यक्ति ioBroker, OpenHAB, होम-असिस्टेंट जैसे विकल्पों को देख सकता है।
लेकिन उन सूचीबद्ध लोगों के नोड.जेएस पर, केवल ioBroker (जब मैं एक लेख लिख रहा हूं, तो ध्यान दिया कि रेडिस भी प्रक्रिया में शामिल है)। और उस समय तक, उन्होंने पता लगाया था कि इंटरप्रोसेस संचार को कैसे व्यवस्थित किया जाए, और रेडिस से निपटने के लिए दिलचस्प था, जिसे हाल ही में सुना गया है।


आप निम्नलिखित विनिर्देश पर भी ध्यान दे सकते हैं:


वेब थिंग एपीआई


युक्ति



Redis इंटरप्रोसेस संचार में मदद करता है, और सामान के लिए डेटाबेस के रूप में भी कार्य करता है।


bobaoskit.worker मॉड्यूल अनुरोध कतार ( bee-queue का उपयोग करते हुए redis शीर्ष पर) होता है, डेटाबेस से अनुरोध / लिखता है, निष्पादित करता है।


उपयोगकर्ता स्क्रिप्ट में, bobaoskit.accessory ऑब्जेक्ट इस विशेष एक्सेसरी के लिए एक अलग bee-queue लिए सुनता है, निर्धारित क्रिया करता है, bobaoskit.sdk ऑब्जेक्ट के माध्यम से मुख्य प्रक्रिया कतार में अनुरोध भेजता है।


प्रोटोकॉल


सभी अनुरोध और प्रकाशित संदेश JSON प्रारूप में तार हैं, method और payload फ़ील्ड शामिल हैं। payload = null भी फ़ील्ड की आवश्यकता होती है।


bobaoskit.worker लिए अनुरोध:


  • विधि: ping , पेलोड: null
  • विधि: get general info , पेलोड: null
  • विधि: clear accessories , पेलोड: null ,
  • विधि: add accessory ,
    पेलोड:

 { id: "accessoryId", type: "switch/sensor/etc", name: "Accessory Display Name", control: [<array of control fields>], status: [<array of status fields>] } 

  • विधि: remove accessory , पेलोड को remove accessory : accessoryId/[acc1id, acc2id, ...]
  • विधि: get accessory info , पेलोड: null/accId/[acc1id, acc2id...]
    payload फ़ील्ड में, आप एक्सेसरी / मास id की null / id भेज सकते हैं। यदि null भेजा जाता है, तो सभी मौजूदा सामानों के बारे में जानकारी वापस आ जाएगी।
  • विधि: get status value , पेलोड: {id: accessoryId, status: fieldId}
    payload फ़ील्ड में आप फॉर्म {id: accessoryId, status: fieldId} , (जहाँ पर status फ़ील्ड फ़ील्ड का एक सरणी हो सकता है) का ऑब्जेक्ट भेज सकते हैं, या payload इस तरह की वस्तुओं का एक सरणी हो सकता है।
  • विधि: update status value , पेलोड: {id: accessoryId, status: {field: fieldId, value: value}
    payload फ़ील्ड में, आप फॉर्म {id: accessoryId, status: {field: fieldId, value: value}} , का एक ऑब्जेक्ट भेज सकते हैं, (जहां status फ़ील्ड एक सरणी हो सकती है {field: fieldId, value: value} , या payload ऐसी वस्तुओं की एक सरणी हो सकती है) की तरह।
  • विधि: control accessory value , पेलोड को control accessory value : {id: accessoryId, control: {field: fieldId, value: value}}
    payload फ़ील्ड में, आप फॉर्म {id: accessoryId, control: {field: fieldId, value: value}} का ऑब्जेक्ट भेज सकते हैं, (जहाँ control फ़ील्ड एक ऐरे हो सकता है {field: fieldId, value: value} , या payload ऐसी वस्तुओं की एक सरणी हो सकती है की तरह।

किसी भी अनुरोध के जवाब में, यदि सफल हो, तो फॉर्म का एक संदेश:


{ method: "success", payload: <...> }


विफलता के मामले में:


{ method: "error", payload: "Error description" }


संदेश निम्नलिखित मामलों में redis PUB/SUB चैनल ( config.json में परिभाषित) में भी प्रकाशित किए जाते हैं: सभी सामान साफ़ किए जाते हैं ( clear accessories ); गौण जोड़ा ( add accessory ); गौण हटा (गौण हटा); गौण अद्यतन स्थिति ( update status value )।


प्रसारण संदेशों में दो फ़ील्ड भी शामिल हैं: method और payload


ग्राहक SDK


विवरण


क्लाइंट SDK ( bobaoskit.accessory ) आपको js स्क्रिप्ट से उपरोक्त विधियों को कॉल करने की अनुमति देता है।


मॉड्यूल के अंदर दो कंस्ट्रक्टर ऑब्जेक्ट हैं। पहला उपरोक्त विधियों तक पहुँचने के लिए एक Sdk ऑब्जेक्ट बनाता है, और दूसरा इन कार्यों के शीर्ष पर एक गौण - एक आवरण बनाता है।


 const BobaosKit = require("bobaoskit.accessory"); //   sdk. //  , //     , //     sdk, const sdk = BobaosKit.Sdk({ redis: redisClient // optional job_channel: "bobaoskit_job", // optional. default: bobaoskit_job broadcast_channel: "bobaoskit_bcast" // optional. default: bobaoskit_bcast }); //   const dummySwitchAcc = BobaosKit.Accessory({ id: "dummySwitch", // required name: "Dummy Switch", // required type: "switch", // required control: ["state"], // requried. ,   . status: ["state"], // required.   . sdk: sdk, // optional. //   ,   sdk   //     redis: undefined, job_channel: "bobaoskit_job", broadcast_channel: "bobaoskit_bcast" }); 

एसडीके ऑब्जेक्ट Promise तरीकों का समर्थन Promise है:


 sdk.ping(); sdk.getGeneralInfo(); sdk.clearAccessories(); sdk.addAccessory(payload); sdk.removeAccessory(payload); sdk.getAccessoryInfo(payload); sdk.getStatusValue(payload); sdk.updateStatusValue(payload); sdk.controlAccessoryValue(payload); 

BobaosKit.Accessory({..}) ऑब्जेक्ट BobaosKit.Accessory({..}) BobaosKit.Sdk(...) ऑब्जेक्ट के शीर्ष पर एक आवरण है।


अगला, मैं दिखाऊंगा कि यह कैसे घूमता है:


 //     self.getAccessoryInfo = _ => { return _sdk.getAccessoryInfo(id); }; self.getStatusValue = payload => { return _sdk.getStatusValue({ id: id, status: payload }); }; self.updateStatusValue = payload => { return _sdk.updateStatusValue({ id: id, status: payload }); }; 

दोनों ऑब्जेक्ट भी EventEmitter
Sdk ready और broadcasted event घटनाओं पर कार्य broadcasted event है।
Accessory घटनाओं के लिए ready कार्यों, error , control accessory value पर कार्य करता है।


उदाहरण


 const BobaosKit = require("bobaoskit.accessory"); const Bobaos = require("bobaos.sub"); // init bobaos with default params const bobaos = Bobaos(); // init sdk with default params const accessorySdk = BobaosKit.Sdk(); const SwitchAccessory = params => { let { id, name, controlDatapoint, stateDatapoint } = params; // init accessory const swAcc = BobaosKit.Accessory({ id: id, name: name, type: "switch", control: ["state"], status: ["state"], sdk: accessorySdk }); //       state //     KNX  bobaos swAcc.on("control accessory value", async (payload, cb) => { const processOneAccessoryValue = async payload => { let { field, value } = payload; if (field === "state") { await bobaos.setValue({ id: controlDatapoint, value: value }); } }; if (Array.isArray(payload)) { await Promise.all(payload.map(processOneAccessoryValue)); return; } await processOneAccessoryValue(payload); }); const processOneBaosValue = async payload => { let { id, value } = payload; if (id === stateDatapoint) { await swAcc.updateStatusValue({ field: "state", value: value }); } }; //      KNX //   state  bobaos.on("datapoint value", payload => { if (Array.isArray(payload)) { return payload.forEach(processOneBaosValue); } return processOneBaosValue(payload); }); return swAcc; }; const switches = [ { id: "sw651", name: "", controlDatapoint: 651, stateDatapoint: 652 }, { id: "sw653", name: " 1", controlDatapoint: 653, stateDatapoint: 653 }, { id: "sw655", name: " 2", controlDatapoint: 655, stateDatapoint: 656 }, { id: "sw657", name: " 1", controlDatapoint: 657, stateDatapoint: 658 }, { id: "sw659", name: "", controlDatapoint: 659, stateDatapoint: 660 } ]; switches.forEach(SwitchAccessory); 

WebSocket एपीआई


bobaoskit.worker ./config.json में परिभाषित WebSocket पोर्ट पर सुनता है।


इनकमिंग अनुरोध JSON स्ट्रिंग्स हैं जिनमें निम्नलिखित फ़ील्ड होनी चाहिए: request_id , method और payload


एपीआई निम्नलिखित अनुरोधों तक सीमित है:


  • विधि: ping , पेलोड: null
  • विधि: get general info , पेलोड: null ,
  • विधि: get accessory info , पेलोड: null/accId/[acc1Id, ...]
  • विधि: get status value , पेलोड: {id: accId, status: field1/[field1, ...]}/[{id: ...}...]
  • विधि: control accessory value , पेलोड: {id: accId, control: {field: field1, value: value}/[{field: .. value: ..}]}/[{id: ...}, ...]

get status value , control accessory value विधियाँ payload फ़ील्ड को एक ऑब्जेक्ट या एक सरणी के रूप में स्वीकार करती हैं। payload अंदर control/status क्षेत्र या तो एकल ऑब्जेक्ट या एक सरणी हो सकते हैं।


सर्वर से निम्नलिखित घटना संदेश भी सभी ग्राहकों को भेजे जाते हैं:


  • विधि: clear accessories , पेलोड: अशक्त
  • विधि: remove accessory , पेलोड remove accessory : एक्सेसरी आईडी
  • विधि: add accessory, payload : {आईडी: ...}
  • विधि: update status value, payload : {आईडी: ...}

dnssd


स्थानीय नेटवर्क पर _bobaoskit._tcp पोर्ट को अनुप्रयोग _bobaoskit._tcp सेवा के रूप में _bobaoskit._tcp करता है, dnssd मॉड्यूल के लिए धन्यवाद।


डेमो



एक अलग लेख लिखा जाएगा कि कैसे आवेदन वीडियो के साथ लिखा गया था और flutter इंप्रेशन।


अंतभाषण


इस प्रकार, सॉफ्टवेयर सामान के प्रबंधन के लिए एक सरल प्रणाली प्राप्त की गई थी।
सहायक उपकरण वास्तविक दुनिया से वस्तुओं के विपरीत हो सकते हैं: बटन, सेंसर, स्विच, थर्मोस्टैट, रेडियो। चूंकि कोई मानकीकरण नहीं है, आप control < == > update में फिट होने वाले किसी भी सामान को लागू कर सकते हैं control < == > update मॉडल।


क्या बेहतर किया जा सकता है:


  1. एक बाइनरी प्रोटोकॉल कम डेटा भेजने की अनुमति देगा। दूसरी ओर, JSON , विकास और समझने के लिए तेज़ है। बाइनरी प्रोटोकॉल को भी मानकीकरण की आवश्यकता है।

बस इतना ही, मुझे किसी भी प्रतिक्रिया की खुशी होगी।

Source: https://habr.com/ru/post/hi437846/


All Articles