From 920ebbb3fde88072c8bc96ecc42077c833dd1219 Mon Sep 17 00:00:00 2001 From: d-sko Date: Fri, 29 Jan 2016 22:00:45 +0100 Subject: [PATCH 1/2] Implemented new options and unified mono/multi mode new: - use getopt_long() for reading options, this makes reading the passed arguments much easier and the order of the passed options does not matter - all options have a long and a short form (e. g. -b and --binary) - new option -p X, --pin=X to set the pin number - new option -s, --silent disables text output, except for errors - new option -u, --user switches to user mode, in this mode the program uses wiringPiSetupSys() instead of wiringPiSetup(), which allows it to run without root privileges but the GPIO pin has to be exported with the gpio-utilty beforehand. improvements: - fixed multi mode when not using binary mode, unified mono/multi mode to remove duplicated code - updated help with new options and reformatted to fit 80 char terminal --- send.cpp | 373 +++++++++++++++++++++++++------------------------------ 1 file changed, 170 insertions(+), 203 deletions(-) diff --git a/send.cpp b/send.cpp index 0ce08cd..ab5680a 100644 --- a/send.cpp +++ b/send.cpp @@ -7,231 +7,198 @@ #include #include #include +#include //#include void printUsage() { - printf("This is rasperry remote, an application to control remote plugs with the Raspberry Pi.\n"); - printf("Based on RCSwitch and wiringPi. See github.com/xkonni/raspberry-remote for further reference.\n"); - printf("Usage: \n sudo send [-b] or:\n sudo send -h\n"); - printf("Where the -b argument switches the instance to binary mode, and the -h option displays this help.\n\n"); - printf("Binary mode means, that instead numbering the sockets by 00001 00010 00100 01000 10000, the sockets\n"); - printf("are numbered in real binary numbers as following: 00001 00010 00011 00100 00101 00110 and so on.\n"); - printf("This means that your sockets need to be setup in this manner, which often includes that the dedicated remote\n"); - printf("is rendered useless, but more than 6 sockets are supported.\n"); + printf("This is rasperry remote, an application to control remote plugs with the\nRaspberry Pi.\n"); + printf("Based on RCSwitch and wiringPi. See github.com/xkonni/raspberry-remote for\nfurther reference.\n"); + printf("Usage: \n sudo send [options] [ ] \n or: sudo send -h\n\n"); + printf("Options:\n\n"); + printf(" -b, --binary:\n"); + printf(" Switches the instance to binary mode.\n"); + printf(" Binary mode means, that instead numbering the sockets by 00001 00010 00100\n"); + printf(" 01000 10000, the sockets are numbered in real binary numbers as following:\n"); + printf(" 00001 00010 00011 00100 00101 00110 and so on.\n"); + printf(" This means that your sockets need to be setup in this manner, which often\n"); + printf(" includes that the dedicated remote is rendered useless, but more than\n"); + printf(" 6 sockets are supported.\n\n"); + printf(" -h, --help:\n"); + printf(" displays this help\n\n"); + printf(" -p X, --pin=X\n"); + printf(" Sets the pin to use to communicate with the sender.\n"); + printf(" Important note: when running as root, pin numbers are wiringPi numbers while\n"); + printf(" in user mode (-u, --user) pin numbers are BCM_GPIO numbers.\n"); + printf(" See http://wiringpi.com/pins/ for details.\n"); + printf(" Default: 0 in normal mode, 17 in user mode\n\n"); + printf(" -s, --silent:\n"); + printf(" Don't print any text, except for errors\n\n"); + printf(" -u, --user:\n"); + printf(" Switches the instance to user mode.\n"); + printf(" In this mode this program does not need root privileges. It is required to\n"); + printf(" export the GPIO pin using the gpio utility. Note that pin numbers are\n"); + printf(" BCM_GPIO numbers in this mode! the export command for the default port is\n"); + printf(" \"gpio export 17 out\". For more information about port numbering see\n"); + printf(" http://wiringpi.com/pins/.\n\n"); } -int multipleSwitch(int argc, char *argv[]) { - unsigned int PIN = 0; +int main(int argc, char *argv[]) { + bool silentMode = false; bool binaryMode = false; + bool userMode = false; + int pin = 0; + int controlArgCount = 0; char *systemCode; - unsigned int unitCode; - unsigned int command; - unsigned int numberOfActuators; - unsigned int i; - - printf("multi Mode \n"); - - command = atoi(argv[argc - 1]); + int unitCode; + int command; + bool multiMode; + + int c; + while (1) { + static struct option long_options[] = + { + {"binary", no_argument, 0, 'b'}, + {"help", no_argument, 0, 'h'}, + {"pin", required_argument, 0, 'p'}, + {"silent", no_argument, 0, 's'}, + {"user", no_argument, 0, 'u'}, + 0 + }; + int option_index = 0; + + c = getopt_long (argc, argv, "bhp:su",long_options, &option_index); + /* Detect the end of the options. */ + if (c == -1) + break; + + switch (c) { + case 'b': + binaryMode = true; + break; + case 'p': + pin = atoi(optarg); + break; + case 's': + silentMode = true; + break; + case 'u': + userMode = true; + break; + case 'h': + printUsage(); + return 0; + } + } - if (argv[1] = "-b") { - binaryMode = true; - numberOfActuators = (argc - 3) / 2; - } else { - numberOfActuators = (argc - 2) / 2; + // When started in user mode, wiringPiSetupSys() is used. In this mode + // wiringPi uses the /sys/class/gpio interface and the GPIO pin are numbered + // by the native Broadcom GPIO numbers, where wiringPi-number 0 translates to + // bcm-number 17... so use this as default if no pin was set with -p + // reference: + // http://wiringpi.com/reference/setup/ + // http://wiringpi.com/pins/ + if (pin == 0 && userMode) { + pin = 17; } - if (wiringPiSetup() == -1) return 1; - piHiPri(20); - RCSwitch mySwitch = RCSwitch(); - mySwitch.setPulseLength(300); - mySwitch.enableTransmit(PIN); - - for (i = 1; i < numberOfActuators + 1; i++) { - - int indexSystemCode = 0; - int indexUnitCode = 0; - - indexSystemCode = 2 + 2 * (i - 1); - indexUnitCode = 1 + 2 * i; - - systemCode = argv[indexSystemCode]; - unitCode = atoi(argv[indexUnitCode]); - - printf("sending systemCode[%s] unitCode[%i] command[%i]\n", systemCode, unitCode, command); - if (binaryMode) { - switch (command) { - case 1: - mySwitch.switchOnBinary(systemCode, unitCode); - break; - case 0: - mySwitch.switchOffBinary(systemCode, unitCode); - break; - default: - printf("command[%i] is unsupported\n", command); - printUsage(); -// return -1; + controlArgCount = argc - optind; + // we need at least 3 args: systemCode, unitCode and command + if (controlArgCount >= 3) { + if (!silentMode) { + if (binaryMode) { + printf("operating in binary mode\n"); } -// return 0; - } else { - switch (command) { - case 1: - mySwitch.switchOn(systemCode, unitCode); - break; - case 0: - mySwitch.switchOff(systemCode, unitCode); - break; - case 2: - // 00001 2 on binary coded - mySwitch.send("010101010001000101010001"); - break; - case 3: - // 00001 2 on as TriState - mySwitch.sendTriState("FFFF0F0FFF0F"); - break; - default: - printf("command[%i] is unsupported\n", command); - printUsage(); -// return -1; + if (userMode) { + printf("operating in user mode\n"); } -// return 0; + printf("using pin %d\n", pin); } - } - return 0; -} -int main(int argc, char *argv[]) { - /** - * output PIN is hardcoded for testing purposes - * see https://projects.drogon.net/raspberry-pi/wiringpi/pins/ - * for pin mapping of the raspberry pi GPIO connector - */ - int PIN = 0; - /** - * using old numbering mode by default, - * see RCSwitch.cpp for differences - */ - bool binaryMode = false; - char *systemCode; - int unitCode; - int command; + char *controlArgs[controlArgCount]; + int i = 0; + while (optind < argc && i < controlArgCount) { + controlArgs[i] = argv[optind++]; + i++; + } + multiMode = controlArgCount > 3; + int numberOfActuators = (controlArgCount - 1) / 2; + // check if there are enough arguments supplied, we need (numberOfActuators * 2) + 1 - printf("test1"); - if (argc > 5) { -// printf("test2"); - /** - * no matter, which mode is used, at least 4 arguments are required: - * 0: command name (send) - * [ - * 1: systemCode - * 2: unitCode - * ]*n - * 3: command - * if there are less arguments, the help should be printed - * and the application should terminate. - */ - multipleSwitch(argc, argv); - return 0; - } - - if (argc < 4) { - /** - * no matter, which mode is used, at least 4 arguments are required: - * 0: command name (send) - * 1: systemCode - * 2: unitCode - * 3: command - * if there are less arguments, the help should be printed - * and the application should terminate. - */ - printUsage(); - return 1; - } - - /** - * This needs to stand after the check of how many arguments are passed, - * because if there is only 1 argument passed, argv[1] is NULL, which - * will result in an error, because a std::string can't be constructed - * by a NULL value. Therefore it is important to terminate the application - * if there are less than 2 arguments (in this case: less than 4 arguments) - * passed. - */ - std::string firstArgument = argv[1]; - - if (firstArgument == "-b" or firstArgument == "--binary") { - if (argc < 5) { - /** - * in binaryMode, 5 arguments are required: - * 0: command name ('send') - * 1: binary operator ('-b') - * 2: systemCode - * 3: unitCode - * 4: command - * if there are less arguments, the help should be printed, - * and the application should terminate. - */ - printUsage(); - return 1; + if (controlArgCount != (numberOfActuators * 2) + 1) { + printf("invalid set of control arguments\nuse or\n"); + printf(" [ ...] \n"); + return 1; } - printf("operating in binary mode...\n"); - binaryMode = true; - //position of data in input is now shifted by 1 because of '-b'-flag - systemCode = argv[2]; - unitCode = atoi(argv[3]); - command = atoi(argv[4]); - } else if (firstArgument == "-h" or firstArgument == "--help" or firstArgument == "-?") { - printUsage(); - } else { - //no binary mode, therefore using normal mode with old numbering - systemCode = argv[1]; - unitCode = atoi(argv[2]); - command = atoi(argv[3]); - } + if (multiMode && !silentMode) { + printf("multi mode\n"); + } - if (wiringPiSetup() == -1) return 1; - piHiPri(20); - printf("sending systemCode[%s] unitCode[%i] command[%i]\n", systemCode, unitCode, command); - RCSwitch mySwitch = RCSwitch(); - mySwitch.setPulseLength(300); - mySwitch.enableTransmit(PIN); - - if (binaryMode) { - switch (command) { - case 1: - mySwitch.switchOnBinary(systemCode, unitCode); - break; - case 0: - mySwitch.switchOffBinary(systemCode, unitCode); - break; - default: - printf("command[%i] is unsupported\n", command); - printUsage(); - return -1; + command = atoi(controlArgs[controlArgCount - 1]); + if (userMode) { + if (wiringPiSetupSys() == -1) return 1; + } else { + if (wiringPiSetup() == -1) return 1; } - return 0; - } else { - switch (command) { - case 1: - mySwitch.switchOn(systemCode, unitCode); - break; - case 0: - mySwitch.switchOff(systemCode, unitCode); - break; - case 2: - // 00001 2 on binary coded - mySwitch.send("010101010001000101010001"); - break; - case 3: - // 00001 2 on as TriState - mySwitch.sendTriState("FFFF0F0FFF0F"); - break; - default: - printf("command[%i] is unsupported\n", command); - printUsage(); - return -1; + piHiPri(20); + RCSwitch mySwitch = RCSwitch(); + mySwitch.setPulseLength(300); + mySwitch.enableTransmit(pin); + + for (i = 0; i < numberOfActuators; i++) { + int indexSystemCode = i * 2; + int indexUnitCode = indexSystemCode + 1; + systemCode = controlArgs[indexSystemCode]; + unitCode = atoi(controlArgs[indexUnitCode]); + + if (!silentMode) { + printf("sending systemCode[%s] unitCode[%i] command[%i]\n", systemCode, unitCode, command); + } + if (binaryMode) { + switch (command) { + case 1: + mySwitch.switchOnBinary(systemCode, unitCode); + break; + case 0: + mySwitch.switchOffBinary(systemCode, unitCode); + break; + default: + printf("command[%i] is unsupported\n", command); + printUsage(); + if (!multiMode) { + return -1; + } + } + } else { + switch (command) { + case 1: + mySwitch.switchOn(systemCode, unitCode); + break; + case 0: + mySwitch.switchOff(systemCode, unitCode); + break; + case 2: + // 00001 2 on binary coded + mySwitch.send("010101010001000101010001"); + break; + case 3: + // 00001 2 on as TriState + mySwitch.sendTriState("FFFF0F0FFF0F"); + break; + default: + printf("command[%i] is unsupported\n", command); + printUsage(); + if (!multiMode) { + return -1; + } + } + } } return 0; + } else { + printUsage(); + return -1; } } From 869a9baa307b390624f48721cea3975bea846808 Mon Sep 17 00:00:00 2001 From: d-sko Date: Sat, 30 Jan 2016 12:45:22 +0100 Subject: [PATCH 2/2] updated readme --- README.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f162c52..5c8b3ce 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,15 @@ https://github.com/Panzenbaby/Raspberry-Remote-for-Windows-10-IoT-Core ## Usage Try if all is working with the send program -* Switch on single socket: `./send.cpp 00001 1 1` +* Switch on single socket: `./send 00001 1 1` +* Switch on multiple sockets: `./send 00001 1 00001 2 00001 3 1` -Pass the `-b`-option to use binary socket numbering instead of the common "only one switch up"-numbering. See [Binary Mode](#binary-mode) for further details. +### Options +* `-b`, `--binary`: Use binary socket numbering instead of the common "only one switch up"-numbering. See [Binary Mode](#binary-mode) for further details. +* `-p X`, `--pin=X` (X=pin number): Sets the pin number to use. Default is 0 in normal mode and 17 in [user mode](#user-mode). +* `-u`, `--user`: Run in user mode. This mode does not need root permissions, but the GPIO pin has to be exported beforehand using the `gpio` command. See [User Mode](#user-mode) for further details. +* `-s`, `--silent`: Disables all text output except for error messages. +* `-h`, `--help`: Display help. ## Binary Mode Most sockets available for purchase use the following numbering scheme: @@ -43,7 +49,7 @@ no. | address C | 00100 D | 00010 E | 00001 - + Of course, this doesn't make much sense, because it limits the maximum of supported sockets to 5 (or 6, if 00000 is included), and is less intuitive. Using real binary numbering would increase the limit of supported sockets per system to 31, and be more intutive. In binary mode, the sockets need to be numbered as below: no. | address @@ -56,9 +62,13 @@ no. | address 8 | 01000 16 | 10000 31 | 11111 - + Note that you need to configure your sockets to this kind of numbering to use this feature. This often includes that the dedicated remote that gets shipped with the sockets often is rendered useless, since it only supports the former way of numbering. - + +## User Mode +Use this mode if you want to use `send` without root permission. The pin must be exported with the `gpio` utility beforehand because it will be used via the `/sys/class/gpio` interface. The command for the default pin is `gpio export 17 out`. The user must be a member of the *gpio* group to access exported gpio pins!. +**Important Note:** pin numbering is different in this mode! While wiringPi uses its own numbering scheme in default mode, this mode requires the native Broadcom GPIO numbers (the default port 0 is 17 in this mode). See the [wiringPi documentation](http://wiringpi.com/pins/) for further details. + ## Daemon Use the daemon in combination with the webinterface * Copy the files in webinterface in your http directory