├── .gitignore ├── package.json ├── README.md ├── LICENSE └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | node_modules 28 | 29 | # Optional npm cache directory 30 | .npm 31 | 32 | # Optional REPL history 33 | .node_repl_history 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tv-remote-cli", 3 | "version": "0.1.4", 4 | "description": "CLI for remotely controlling your Smart TV", 5 | "main": "index.js", 6 | "bin": { 7 | "tv-remote": "index.js" 8 | }, 9 | "global": true, 10 | "dependencies": { 11 | "async": "^2.0.0-rc.2", 12 | "find-tv": "^0.1.2", 13 | "samsung-remote": "git+https://github.com/Glavin001/samsung-remote.git#patch-1", 14 | "vorpal": "^1.10.9" 15 | }, 16 | "devDependencies": {}, 17 | "scripts": { 18 | "test": "echo \"Error: no test specified\" && exit 1", 19 | "start": "node index.js" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/Glavin001/tv-remote-cli.git" 24 | }, 25 | "keywords": [ 26 | "tv", 27 | "remote", 28 | "samsung", 29 | "cli", 30 | "control" 31 | ], 32 | "author": "Glavin Wiechert", 33 | "license": "MIT", 34 | "bugs": { 35 | "url": "https://github.com/Glavin001/tv-remote-cli/issues" 36 | }, 37 | "homepage": "https://github.com/Glavin001/tv-remote-cli#readme" 38 | } 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tv-remote-cli 2 | [![NPM](https://nodei.co/npm/tv-remote-cli.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/tv-remote-cli/) 3 | > CLI for remotely controlling your Smart TV 4 | 5 | --- 6 | 7 | ## Installation 8 | 9 | ```bash 10 | npm install -g tv-remote-cli 11 | ``` 12 | 13 | ## Features 14 | 15 | - Currently only supports Samsung Smart TVs. See [`samsung-remote` package](https://github.com/natalan/samsung-remote) for more information. 16 | - Send TV commands to Smart TV 17 | - Automatically find and connect to Smart TV 18 | 19 | ```bash 20 | connect 192.168.1.126 21 | ``` 22 | 23 | or automatically find Smart TV with 24 | 25 | ```bash 26 | connect 27 | ``` 28 | 29 | - Send commands repeatedly 30 | 31 | Volume Up 3 times 32 | 33 | ``` 34 | volup 3 35 | ``` 36 | 37 | 38 | 39 | ## Usage 40 | 41 | For list of all commands run `help` command. 42 | 43 | Example: 44 | 45 | ``` 46 | ❯ tv-remote 47 | 48 | TV$ connect 49 | Connecting to 192.168.1.126 50 | TV$ volup 51 | TV$ voldown 52 | TV$ volup 53 | TV$ voldown 3 54 | TV$ volup 4 500 55 | TV$ exit 56 | ``` 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Glavin Wiechert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | const vorpal = require('vorpal')(); 4 | const SamsungRemote = require('samsung-remote'); 5 | const findTV = require('find-tv'); 6 | const async = require('async'); 7 | 8 | let remote = null 9 | const send = function(key, callback) { 10 | if (remote) { 11 | return remote.send("KEY_"+key, callback); 12 | } else { 13 | return callback(new Error("No remote.")); 14 | } 15 | } 16 | 17 | const remoteKeys = [ 18 | "ENTER","EXIT", 19 | "MENU","UP","DOWN","LEFT","RIGHT", 20 | "3","VOLUP","4","5","6","VOLDOWN","7","8","9", 21 | "MUTE","CHDOWN","0", 22 | "CHUP","PRECH","GREEN","YELLOW","CYAN","ADDDEL", 23 | "SOURCE","INFO","PIP_ONOFF","PIP_SWAP","PLUS100","CAPTION","PMODE", 24 | "TTX_MIX","TV","PICTURE_SIZE","AD","PIP_SIZE","MAGIC_CHANNEL", 25 | "PIP_SCAN","PIP_CHUP","PIP_CHDOWN","DEVICE_CONNECT", 26 | "HELP","ANTENA","CONVERGENCE","11","12","AUTO_PROGRAM", 27 | "FACTORY","3SPEED","RSURF","ASPECT","TOPMENU","GAME","QUICK_REPLAY", 28 | "STILL_PICTURE","DTV","FAVCH","REWIND","STOP","PLAY","FF","REC","PAUSE", 29 | "TOOLS","INSTANT_REPLAY","LINK","FF_","GUIDE","REWIND_","ANGLE","RESERVED1", 30 | "ZOOM1","PROGRAM","BOOKMARK","DISC_MENU","PRINT","RETURN","SUB_TITLE","CLEAR", 31 | "VCHIP","REPEAT","DOOR","OPEN","WHEEL_LEFT","POWER","SLEEP","2","DMA","TURBO", 32 | "1","FM_RADIO","DVR_MENU","MTS","PCMODE","TTX_SUBFACE","CH_LIST","RED","DNIe", 33 | "SRS","CONVERT_AUDIO_MAINSUB","MDC","SEFFECT","DVR","DTV_SIGNAL","LIVE", 34 | "PERPECT_FOCUS","HOME","ESAVING","WHEEL_RIGHT","CONTENTS","VCR_MODE", 35 | "CATV_MODE","DSS_MODE","TV_MODE","DVD_MODE","STB_MODE","CALLER_ID", 36 | "SCALE","ZOOM_MOVE","CLOCK_DISPLAY","AV1","SVIDEO1","COMPONENT1", 37 | "SETUP_CLOCK_TIMER","COMPONENT2","MAGIC_BRIGHT","DVI","HDMI","W_LINK", 38 | "DTV_LINK","APP_LIST","BACK_MHP","ALT_MHP","DNSe","RSS","ENTERTAINMENT", 39 | "ID_INPUT","ID_SETUP","ANYNET","POWEROFF","POWERON","ANYVIEW","MS","MORE", 40 | "PANNEL_POWER","PANNEL_CHUP","PANNEL_CHDOWN","PANNEL_VOLUP","PANNEL_VOLDOW", 41 | "PANNEL_ENTER","PANNEL_MENU","PANNEL_SOURCE","AV2","AV3","SVIDEO2","SVIDEO3", 42 | "ZOOM2","PANORAMA","4_3","16_9","DYNAMIC","STANDARD","MOVIE1","CUSTOM", 43 | "AUTO_ARC_RESET","AUTO_ARC_LNA_ON","AUTO_ARC_LNA_OFF","AUTO_ARC_ANYNET_MODE_OK", 44 | "AUTO_ARC_ANYNET_AUTO_START","AUTO_FORMAT","DNET","HDMI1","AUTO_ARC_CAPTION_ON", 45 | "AUTO_ARC_CAPTION_OFF","AUTO_ARC_PIP_DOUBLE","AUTO_ARC_PIP_LARGE","AUTO_ARC_PIP_SMALL", 46 | "AUTO_ARC_PIP_WIDE","AUTO_ARC_PIP_LEFT_TOP","AUTO_ARC_PIP_RIGHT_TOP", 47 | "AUTO_ARC_PIP_LEFT_BOTTOM","AUTO_ARC_PIP_RIGHT_BOTTOM","AUTO_ARC_PIP_CH_CHANGE", 48 | "AUTO_ARC_AUTOCOLOR_SUCCESS","AUTO_ARC_AUTOCOLOR_FAIL","AUTO_ARC_C_FORCE_AGING", 49 | "AUTO_ARC_USBJACK_INSPECT","AUTO_ARC_JACK_IDENT","NINE_SEPERATE","ZOOM_IN","ZOOM_OUT", 50 | "MIC","HDMI2","HDMI3","AUTO_ARC_CAPTION_KOR","AUTO_ARC_CAPTION_ENG","AUTO_ARC_PIP_SOURCE_CHANGE", 51 | "HDMI4","AUTO_ARC_ANTENNA_AIR","AUTO_ARC_ANTENNA_CABLE","AUTO_ARC_ANTENNA_SATELLITE", 52 | "EXT1","EXT2","EXT3","EXT4","EXT5","EXT6","EXT7","EXT8","EXT9","EXT10", 53 | "EXT11","EXT12","EXT13","EXT14","EXT15","EXT16","EXT17","EXT18","EXT19", 54 | "EXT20","EXT21","EXT22","EXT23","EXT24","EXT25","EXT26","EXT27","EXT28", 55 | "EXT29","EXT30","EXT31","EXT32","EXT33","EXT34","EXT35","EXT36","EXT37", 56 | "EXT38","EXT39","EXT40","EXT41" 57 | ]; 58 | 59 | // Add commands 60 | vorpal 61 | .command("connect [ip]", "Connect to TV") 62 | .action(function(args, callback) { 63 | if (args.ip) { 64 | remote = new SamsungRemote({ 65 | ip: args.ip // '192.168.1.126' // required: IP address of your Samsung Smart TV 66 | }); 67 | this.log('Connecting to '+args.ip); 68 | callback(); 69 | } else { 70 | findTV((error, ip) => { 71 | if (error) { 72 | return callback(error); 73 | } 74 | if (!ip) { 75 | return callback(new Error('No Smart TV found.')); 76 | } 77 | this.log('Connecting to '+ip); 78 | remote = new SamsungRemote({ 79 | ip: ip 80 | }); 81 | callback(); 82 | }); 83 | } 84 | }); 85 | vorpal 86 | .command("alive", "Check if TV is alive") 87 | .action(function(args, callback) { 88 | if (remote) { 89 | return remote.isAlive((error) => { 90 | if (error) { 91 | this.log("TV is offline."); 92 | } else { 93 | this.log("TV is alive."); 94 | } 95 | return callback(); 96 | }); 97 | } else { 98 | return callback(new Error("No remote.")); 99 | } 100 | }); 101 | 102 | for (let key of remoteKeys) { 103 | let commandName = key.toLowerCase();//.split('_').join(' '); 104 | // Check to see if command already exists 105 | if (vorpal.find(commandName)) { 106 | commandName = `tv_${commandName}`; 107 | } 108 | let command = `${commandName} [repeat] [delay]`; 109 | // Add command 110 | vorpal 111 | .command(command, `Press ${commandName} key (KEY_${key})`) 112 | .action(function(args, callback) { 113 | let repeat = args.repeat || 1; 114 | let delay = args.delay || 300; 115 | let tasks = []; 116 | for (var i=1; i<=repeat; i++) { 117 | tasks.push(key); 118 | if (i!==repeat) { 119 | tasks.push(delay); 120 | } 121 | } 122 | async.eachSeries(tasks, (task, callback) => { 123 | if (typeof task === "string") { 124 | return send(task, callback); 125 | } else { 126 | return setTimeout(callback, task); 127 | } 128 | }, callback); 129 | }); 130 | } 131 | 132 | 133 | vorpal 134 | .delimiter('TV$') 135 | .show(); 136 | 137 | --------------------------------------------------------------------------------