├── CONTRIBUTING.md ├── README.md ├── cast_moderator_centipede_arduino.ino └── LICENSE /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Community Guidelines 27 | 28 | This project follows 29 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Copyright 2022 Google LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | # Cast Moderator Centipede 16 | Cast Moderator Centipede is an Arduino script used to setup Cast Moderator 17 | in bulk. The script is compiled and uploaded to a keyboard enabled micro controller. 18 | The Arduino is then powered or executed and walks through the setup flow. 19 | [Setup Example Video](https://youtu.be/mqOyv3sQdOw) 20 | The [eeprom branch](https://github.com/google/cast-moderator-centipede/tree/eeprom) can be used to setup multiple Cast Moderators and automatically change accounts. It requires using an Arduino with EEPROM memory. 21 | 22 | ## Materials 23 | - Google Chromecast 24 | - Arduino with HID Keyboard functionality 25 | - [Arduino Micro](https://store-usa.arduino.cc/products/arduino-micro) for example 26 | - USB splitter with USB-C Data and Power ports 27 | - Tested using [Anker USB-C, Hub Power Expand 6-in-1](https://www.amazon.com/dp/B08C9HZ5YT/ref=redir_mobile_desktop?_encoding=UTF8&aaxitk=7ecf2e6cb8dd44356111dfafbdd8d3d8&content-id=amzn1.sym.cf8fc959-74aa-4850-a250-1b1a4e868e60%3Aamzn1.sym.cf8fc959-74aa-4850-a250-1b1a4e868e60&hsa_cr_id=8749440340201&pd_rd_plhdr=t&pd_rd_r=01294ba4-e1ad-486e-97f6-f5f486a7d4ad&pd_rd_w=jTWat&pd_rd_wg=QRjP9&qid=1666026880&ref_=sbx_be_s_sparkle_lsi4d_asin_2_title&sr=1-3-9e67e56a-6f64-441f-a281-df67fc737124) 28 | 29 | 30 | ## Steps 31 | 1. Clone this repo to your local device. 32 | 2. Edit in an Arduino IDE to enter your WifFi SSID, Password, Google Workspace Username, and Password. 33 | - Optionally adjust timings where needed to accommodate network speed and potential downloads. 34 | - When creating accounts on the domain use the same password. Secure accounts by turning off services such as gmail and drive which are not needed. 35 | - Google accounts can only be used on up to 90 devices. 36 | - When using a non-Google SSO it's best to place the cast accounts in an org unit set to [Google as the SSO](https://cloud.google.com/blog/products/identity-security/google-now-supports-multi-idp-sso-in-google-workspace-and-google-cloud). 37 | 3. Compile and upload to the arduino. 38 | 4. Connect the tail of your USB-c splitter to the Chromecast. 39 | 5. Connect the Chromecast to the HDMI. 40 | 6. Connect the Power to the USB and let it boot. 41 | 7. When prompted pair the remote. 42 | 8. Once paired plug in or reset the Arduino. Code will begin the click after the set delay; 10 seconds. 43 | 9. Once asked to explore thr Chromecast it can be disconnected and installed in a Classroom. When booted it will load Cast Moderator immediately. 44 | -------------------------------------------------------------------------------- /cast_moderator_centipede_arduino.ino: -------------------------------------------------------------------------------- 1 | /* Copyright 2022 Google LLC 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. */ 14 | 15 | #include 16 | 17 | 18 | /* 19 | https://youtu.be/mqOyv3sQdOw 20 | Pairing the remote is a first step. When bulk setting up a single 21 | remote can be used and the packaged remotes paired later in the 22 | classroom using the Chromecast button long press to pair. 23 | 24 | After pairing the language select screen will appear. 25 | The Arduino code below can be run at this point. 26 | */ 27 | 28 | #define wifi_name "" // Define SSID for your wireless connection. 29 | #define wifi_pass "" // Define the password for your wireless connection. 30 | #define account_name "" // Define Google Workspace account used to connect for casting. 31 | #define account_pass "" // Define Google Workspace account password used to connect for casting. 32 | 33 | /* 34 | If the language of setup is not English select the 35 | position of the language on a 0 index 36 | */ 37 | int languagepos = 0; //Default: 0 38 | 39 | /** 40 | * Sets the position of the Security selection for the network 41 | */ 42 | int security_type = 0; //0 for none, 1 for WEP, 2 for WPA/WPA2-Personal 43 | 44 | /** 45 | * Navigates to the Manual entry of network. 46 | */ 47 | int wifipos = 20; //20 down clicks. Click and enter manually 48 | 49 | /** 50 | * Amount of time in seconds to wait for the update 51 | */ 52 | int updatewait = 900; //Default: 900 53 | 54 | /** 55 | * The setup function runs once when you press the reset button on the 56 | * Arduino or power-on the Arduino 57 | * 58 | * @return {void} 59 | */ 60 | 61 | void setup() { 62 | Keyboard.begin(); //begin the keyboard. 63 | wait(10); //Provide a buffer to cancel by removing the arduino 64 | start(); //Run the Chromecast setup 65 | } 66 | 67 | /** 68 | * The start function runs each step of the setup process with waits for UI 69 | * rendering between. Timing can be adjusted here. Going too fast will 70 | * result in setup failures and a requirement to factory reset or complete 71 | * manually. 72 | * @return {void} 73 | */ 74 | void start() { 75 | selectLanguage(); //selects the language at the languagepos index assigned above 76 | wait(1); //waiting 1 second to allow UI to render 77 | setupOnTv(); //Select setup to be on the TV 78 | wait(1); //waiting 1 second to allow UI to render 79 | wifi(); //Select WiFi and enter credentials 80 | wait(60); //Connecting. If your network is potentially slower increase this wait to accommodate 81 | wait(updatewait); //Wait for the Update. May need to be adjusted for slower networks. 82 | konami(); //Enters the unique setup code 83 | wait(3); //waiting 3 second to allow UI to render 84 | optIn(); //selects the OptIn dialogs. Please ensure manual review before proceeding. 85 | wait(8); //waiting 8 second to allow UI to render 86 | googleAccount(); //Enters the Google account credentials for Cast Moderator 87 | wait(8); //waiting 8 second to allow UI to render 88 | legalAccepts(); //Accepts the legal notifications. Please ensure manual review before proceeding. 89 | wait(5); //waiting 5 second to allow UI to render 90 | googleServices(); //accepts or deselects the the Google Services. Please ensure manual review before proceeding. 91 | wait(5); //waiting 1 second to allow UI to render 92 | noRemoteSetup(); //Select No Remote setup for audio controls. Audio controls can be setup in room later. 93 | } 94 | 95 | /** 96 | * No loop required for this functionality. 97 | * Advanced users can assign a pin to a button 98 | * for use in triggering the start function. 99 | */ 100 | void loop() { 101 | } 102 | 103 | /** 104 | * Select the Language 105 | * @return {void} 106 | */ 107 | void selectLanguage() { 108 | if (languagepos > 0) { 109 | for (int i = 0; i <= languagepos; i++) { 110 | Keyboard.write(KEY_DOWN_ARROW); 111 | wait(1); 112 | } 113 | } 114 | Keyboard.write(KEY_RETURN); 115 | } 116 | 117 | /** 118 | * Skip the Google Home setup as it does not allow the setup 119 | * for Cast Moderator. 120 | * Select Setup on TV 121 | * @return {void} 122 | */ 123 | void setupOnTv() { 124 | wait(2); 125 | Keyboard.write(KEY_DOWN_ARROW); 126 | wait(1); 127 | Keyboard.write(KEY_RETURN); 128 | wait(5); 129 | } 130 | 131 | /** 132 | * Set the WiFi credentials 133 | * @return {void} 134 | */ 135 | void wifi() { 136 | if (wifipos > 0) { 137 | for (int i = 0; i <= wifipos; i++) { 138 | Keyboard.write(KEY_DOWN_ARROW); 139 | } 140 | } 141 | Keyboard.write(KEY_RETURN); 142 | wait(1); 143 | Keyboard.print(wifi_name); 144 | Keyboard.write(KEY_RETURN); 145 | wait(1); 146 | if(security_type>0){ 147 | for (int i = 0; i <= security_type; i++) { 148 | Keyboard.write(KEY_DOWN_ARROW); 149 | wait(1); 150 | } 151 | } 152 | Keyboard.write(KEY_RETURN); 153 | wait(1); 154 | Keyboard.print(wifi_pass); 155 | Keyboard.write(KEY_RETURN); 156 | } 157 | 158 | /** 159 | * Execute the konami code to get access to Cast Moderator 160 | * @return {void} 161 | */ 162 | void konami() { 163 | Keyboard.write(KEY_ESC); //Closes the keyboard 164 | wait(1); //Waiting 1 second to allow UI to render 165 | back(); //Returns to the wifi for special code entry 166 | wait(5); //waiting 5 second to allow UI to render 167 | for (int i = 0; i < 7; i++) { 168 | Keyboard.write(KEY_UP_ARROW); 169 | } 170 | } 171 | 172 | /** 173 | * Agree to Cast Moderator selections and reminders 174 | * @return {void} 175 | */ 176 | void optIn() { 177 | wait(1); 178 | Keyboard.write(KEY_RETURN); //Using Cast Moderator 179 | wait(3); 180 | Keyboard.write(KEY_RETURN); //Organization Access 181 | wait(1); 182 | Keyboard.write(KEY_UP_ARROW); 183 | wait(1); 184 | Keyboard.write(KEY_RETURN); //Setup 185 | wait(1); 186 | Keyboard.write(KEY_RETURN); //Device Isn't Private 187 | wait(1); 188 | Keyboard.write(KEY_RETURN); //Cast Moderator is set up 189 | } 190 | 191 | /** 192 | * Enter the Google Account credentials 193 | * @return {void} 194 | */ 195 | void googleAccount() { 196 | Keyboard.print(account_name); 197 | Keyboard.write(KEY_RETURN); 198 | wait(5); 199 | Keyboard.print(account_pass); 200 | Keyboard.write(KEY_RETURN); 201 | } 202 | 203 | /** 204 | * Accept Terms of Service and Additional Legal 205 | * @return {void} 206 | */ 207 | void legalAccepts() { 208 | Keyboard.write(KEY_RETURN); //Accept TOS 209 | wait(3); 210 | Keyboard.write(KEY_RETURN); //Accept Additional Legal Terms 211 | } 212 | 213 | /** 214 | * Deselect or accept Google Services. 215 | * @return {void} 216 | */ 217 | void googleServices() { 218 | wait(2); 219 | Keyboard.write(KEY_RETURN); 220 | } 221 | 222 | /** 223 | * Skip the the Audio setup with the remote. This can be completed later. 224 | * @return {void} 225 | */ 226 | void noRemoteSetup() { 227 | Keyboard.write(KEY_RIGHT_ARROW); 228 | wait(1); 229 | Keyboard.write(KEY_RIGHT_ARROW); 230 | wait(1); 231 | Keyboard.write(KEY_RETURN); 232 | } 233 | 234 | /** 235 | * Wait in integer seconds 236 | * @param {integer} 237 | * @return {void} 238 | */ 239 | void wait(int seconds = 1); 240 | void wait(int seconds) { 241 | for (int i = 0; i < seconds; i++) { 242 | blink(); 243 | } 244 | } 245 | 246 | /** 247 | * Back key signal 248 | * @return {void} 249 | */ 250 | void back() { 251 | Keyboard.press(KEY_LEFT_GUI); 252 | delay(200); 253 | Keyboard.write(KEY_BACKSPACE); 254 | wait(1); 255 | Keyboard.releaseAll(); 256 | } 257 | 258 | /** 259 | * LED Blink 260 | * @return {void} 261 | */ 262 | void blink() { 263 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on 264 | delay(500); // wait for half a second 265 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off 266 | delay(500); // wait for half a second 267 | } 268 | 269 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2022 Google LLC 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. --------------------------------------------------------------------------------