From ae4facc68025761cf8fc2a6baabb7cc8073bb2fc Mon Sep 17 00:00:00 2001 From: Tim van Cann Date: Mon, 11 Feb 2019 13:31:43 +0100 Subject: [PATCH] Google pubsub (#8153) * Add basic documentation for google_pubsub * Add guide to saving data * Fix markdown * :pencil: Tweaks * Make configuration quick-start proof. * :pencil2: Tweaks * Bump release version to 0.87 * Bump release * Update category to History --- source/_components/google_pubsub.markdown | 86 ++++++++++++++++++ .../images/supported_brands/google-pubsub.png | Bin 0 -> 12775 bytes 2 files changed, 86 insertions(+) create mode 100644 source/_components/google_pubsub.markdown create mode 100644 source/images/supported_brands/google-pubsub.png diff --git a/source/_components/google_pubsub.markdown b/source/_components/google_pubsub.markdown new file mode 100644 index 00000000000..c7738613a31 --- /dev/null +++ b/source/_components/google_pubsub.markdown @@ -0,0 +1,86 @@ +--- +layout: page +title: "Google Pub/Sub" +description: "Setup for Google Pub/Sub integration" +date: 2019-01-12 13:30 +sidebar: true +comments: false +sharing: true +footer: true +logo: google-pubsub.png +ha_category: History +ha_release: 0.88 +--- + +The `google_pubsub` component allows you to hook into the Home Assistant event bus and send events to [Google Cloud Pub/Sub](https://cloud.google.com/pubsub/docs/overview). The current [free tier](https://cloud.google.com/free/) of GCP should allow you to sync about 1 event every 2 seconds on average (2 million invocations per month). + +## {% linkable_title First time setup %} + +This assumes you already have a Google Cloud project. If you don't, please create one in the [Google Cloud Console](https://console.cloud.google.com/projectcreate) + +You need to create a Service Account key in the [Google Cloud API Console](https://console.cloud.google.com/apis/credentials/serviceaccountkey) +- Choose a new "New Service Account", give it a name and leave the key type as JSON +- Select the role: Pub/Sub Publisher + +This will download the Service Account JSON key to your machine. Do NOT share this with anyone. Place this file in your Home Assistant config folder. + +Next, create a Google Pub/Sub topic in the [Google Cloud API Console](https://console.cloud.google.com/cloudpubsub/topicList). The topic name will become something like `projects/project-198373/topics/topic-name`. Note the last part only (the name you chose): `topic-name`. + + +## {% linkable_title Configuration %} + +Add the following lines to your `configuration.yaml` file: + +```yaml +# Example configuration.yaml entry +google_pubsub: + project_id: YOUR_PROJECT_ID + topic_name: YOUR_TOPIC_NAME + credentials_json: CREDENTIALS_FILENAME +``` + +{% configuration %} +project_id: + description: Project ID from the Google console (looks like `words-2ab12`). + required: true + type: string +topic_name: + description: The Pub/Sub topic name. + required: true + type: string +credentials_json: + description: The filename of the Google Service Account JSON file. + required: true + type: string +filter: + description: Filter domains and entities for Google Cloud Pub/Sub. + required: false + type: map + default: Includes all entities from all domains + keys: + include_domains: + description: List of domains to include (e.g., `light`). + required: false + type: list + exclude_domains: + description: List of domains to exclude (e.g., `light`). + required: false + type: list + include_entities: + description: List of entities to include (e.g., `light.attic`). + required: false + type: list + exclude_entities: + description: List of entities to include (e.g., `light.attic`). + required: false + type: list +{% endconfiguration %} + +

+ Not filtering domains or entities will send every event to Google PubSub, thus hitting the free tier limit very fast. Be sure to fill in this configuration parameter or have a paid subscription for Google Cloud. +

+ +### {% linkable_title Saving the data using a Google Cloud Function %} + +To save your data automatically to BigQuery, follow the [instructions here](https://github.com/timvancann/home-assistant-pubsub-cloud-function). The current [free tier](https://cloud.google.com/free/) of GCP should allow to store up to 10GB of data. + diff --git a/source/images/supported_brands/google-pubsub.png b/source/images/supported_brands/google-pubsub.png new file mode 100644 index 0000000000000000000000000000000000000000..0ff9a4df927c740a4a67a30facd7b86516e9d17f GIT binary patch literal 12775 zcmd6OWm}tF({*sSBE?;c7cXwby*LGe6?b=cDemrtAjPeCpak~@ha$z@<;`^;?~iys zBp;Gv_Bpfn$eOk1j8RvW!$K!T2LJ$A3i2|V0011@e;-t2*e^Z-i5>s|H9$c|@{4!g z$(mOlz4n5@`9??EkHPQ>$iTo)B~^GO?9i0dK00{Dzdrs6MZxce5I-nz6(=DMKW9mz zAxo%-AnAk#NB3$*n^{Tfy9ftTW_vj!(PttjFW5 zBN$f-l_vcE-j`izGXn8%pou}cC#nY>?fruYF@Ox&1_@wF1`kNP1pbjo&OsY6L~~~j z{wk3LmY@Vw51BG(696JV-M|V#bsPT7767{RthC>&k%I>$3Vw+>=%Efby+MWRMLK5!T+LxQ z+NXx67vyO^vf+M39KcMO|N9{+8XL*E>bBdlbx#=6pG3k78j>LU;RFDtg-_I$NlMmy zQ9ov_QCIV76;p2g(fH`0_vEHH;VA>7+TfzjT0&hPMEkS}*PaAC_y z_^tcMxI02!qKC*!MPCpApH3ul@}D-)^#i@Z!Lzn%Cw_0ap3JoRV^^rD%e*wm9Q0DCO)bz@JF4Z!EJhc^jI8Ov+K1Cm>Kp1Y4LGqF~@E$ zk>LntE$SS$DI%h^nn|iB@qmM3wVPmrxYgeA*^d<3eS9LjwvmRk*)#f*fVo8J_5=cl zQhyJ9;>dkVTiasuRjNTVFC2J>Q=j!4g+TuqdSdkgF^LZX|~vm+VglZAMZECz;rG)#=n(JQzYe zVH-Kai*8Wuq!))Ui%ri8+s3-IOqvo0h2%6*qDI=17YV@y13x=xqeTepz(->eTh4se z+fc0)gmGuwN3X7z2Kz*Y`hGTtx#SDKuS5$LY^FjEjh$=o#(#5B%gG{!EPk)heWweUcw|7elN3WvuHH>UgzH z)b_`H{ER}|@cGY*`JBHMdExQ$kNtSbHY?{6hqWh}YPpoZbr8Z${|aIVW~oM`2Gb^` zJ*pBT%5hyuK>OQAAHvghVk~H(nezFWW4UqM@z`G!^Q}NH`q1S6{W)17gn9B%7&iZg z%R+q;kgT%n3FxsI*(SZKrf{V~2gIn<_@LHI5DhuAQJ#A~SFP)-& z`1_BO|6V0G)RLNa=ItXuHn*s$8Gn47yqfn|j69PU#?6EYlYWYn zwe;)D`+-%iMT?mahU*yEGBnuo?XN&iEx(1W@K#FOzVk(lm=s31Bf+*a*$gmt{vn|g$7tUl1Hx}L-E**i zod9@B@NTL#1BAd$ia|$6P?BE1P~0%$43j(WQVO-mYbT5 zF_hy(id*!!x7M3cV`U-e&YResbryVoCxm?kJ;Wni`$mVZuH6%~NcWinIAx+%R@L-m zVkpN-tD#y;W4`?=7+72m+be!MVNtt{XSKNH5~{EAX`1g@Ku|1%UF&7t}j=$sD=2gw);YCdV3 z8=%cs2T~sOb2JqDO7ozT7f)u>xC`Xn5Ha~B=eaZ;CT5VDnd*6gGps5oG2BDu9vK1n zbFcAr7?=%fR_H5gac{0Rtjy%iT6hTMfmw>2^fnIg2#VE5>6#}BYxs3;uPi|8R2I(C zmQQH}iE4j`bCs=$h3)I!`Q@}7#gj*)E~W*e7rB9ccWdBN4=hrP%@O;P=cZ+SL5WM2M;(fBKz3b^bK7^Er`Va4bgP`g!IIp zj4Q@Pw*0!IO#U{s<{h58ymO?%I+J%!3HL^SMn?6uL}wHkpRrxQKVot>uigk*f}wj` zOj@TB&2|0D-LJU?ny&S0hGvK~bZ0mW%%OaiMN+e(tEjN@1sWu)#VR0HidlOIw{*x; zsv?Hv_u!Hfo(qp{R9f&6YijP7c4y1r>5rFoYu?gp(ix{)$QrCHH($vjQQ/D+x8 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