mirror of
				https://github.com/taigrr/tplinkController
				synced 2025-01-18 04:43:13 -08:00 
			
		
		
		
	Add ability to do first-time plug setup
This commit is contained in:
		
							parent
							
								
									f01121c37c
								
							
						
					
					
						commit
						b66401d5a1
					
				
							
								
								
									
										46
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								README.md
									
									
									
									
									
								
							| @ -1,7 +1,8 @@ | ||||
| # hs100 | ||||
| 
 | ||||
| A tool for using TP-Link HS100/HS105/HS110 wi-fi smart plugs. You can turn | ||||
| them on or off, reboot them, and factory reset them. | ||||
| them on and off, reboot them, and so on. You can even set them up without | ||||
| using the app (see Initial Setup). | ||||
| 
 | ||||
| Tested to work on Linux, OSX, IRIX, and Windows under WSL. | ||||
| 
 | ||||
| @ -12,16 +13,53 @@ Loosely based on [pyHS100](https://github.com/GadgetReactor/pyHS100) and | ||||
| 
 | ||||
| `hs100 <ip> <command>` | ||||
| 
 | ||||
| Command can be: | ||||
| - `on`: turn the power on | ||||
| Commands: | ||||
| - `associate <ssid> <key> <key_type>`: set wifi AP to connect to. get your | ||||
| key\_type by doing a scan | ||||
| - `factory-reset`: reset the plug to factory settings | ||||
| - `off`: turn the power off | ||||
| - `on`: turn the power on | ||||
| - `reboot`: reboot the plug | ||||
| - `reset-yes-really`: factory reset the plug | ||||
| - `scan`: scan for nearby wifi APs (probably only 2.4 GHz ones) | ||||
| - `set_server <url>`: set cloud server to \<url\> instead of TP-Link's | ||||
| - Alternatively, you can supply a JSON string to be sent directly to the | ||||
| device. Note that the JSON string must be quoted, like so: | ||||
| `hs100 <ip> '{"system":{"set_relay_state":{"state":1}}}'` | ||||
| 
 | ||||
| ## Initial Setup | ||||
| 
 | ||||
| According to TP-Link, initial setup of the plugs is performed by installing | ||||
| their "Kasa" app on your smartphone (free account required), and using its | ||||
| setup tool. This sucks and I do not recommend it. Instead, follow these | ||||
| alternative instructions. | ||||
| 
 | ||||
| You want to get the plug into the "blinking amber and blue" state, in which | ||||
| it will spin up its own AP and await commands. If you have a brand new plug, | ||||
| then it should do this automatically. Otherwise, hold down one of the buttons | ||||
| (depending on your model) for about 5 seconds, until its light blinks amber | ||||
| and blue. | ||||
| 
 | ||||
| You should see a wifi AP called "TP-Link\_Smart Plug\_XXXX" or similar. | ||||
| Connect to this AP. You will be given an IP of 192.168.0.100, with the plug | ||||
| at 192.168.0.1. | ||||
| 
 | ||||
| Issue the following commands to the plug: | ||||
| - Factory reset the plug to get rid of any settings from a previous owner: | ||||
| `hs100 192.168.0.1 factory-reset`. You will be disconnected from its wifi AP. | ||||
| Once the factory reset is done (usually a few seconds), reconnect to the | ||||
| plug's AP. | ||||
| - Disable cloud nonsense by setting a bogus server URL: `hs100 192.168.0.1 set_server localhost` | ||||
| - Scan for your wifi AP using `hs100 192.168.0.1 scan`. Find your AP in the | ||||
| list and note its `key_type`; you will need this to associate. | ||||
| - Associate with your AP using `hs100 192.168.0.1 <ssid> <password> <key_type>` | ||||
| . Your key\_type is a number that indicates the kind of wifi security that | ||||
| your AP is using. You can find it by doing a wifi scan (see previous step). | ||||
| 
 | ||||
| If the light turns solid amber, then it was unable to associate-- factory | ||||
| reset the plug and try again. Otherwise, the light on your plug will change | ||||
| first to blinking blue, then to solid blue indicating that it has successfully | ||||
| connected to your AP. | ||||
| 
 | ||||
| ## Todo | ||||
| 
 | ||||
| - better error checking | ||||
|  | ||||
							
								
								
									
										89
									
								
								hs100.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								hs100.c
									
									
									
									
									
								
							| @ -2,9 +2,69 @@ | ||||
| #include <inttypes.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <errno.h> | ||||
| #include "version.h" | ||||
| #include "comms.h" | ||||
| 
 | ||||
| char *handler_associate(int argc, char *argv[]) | ||||
| { | ||||
| 	if(argc < 6) { | ||||
| 		fprintf(stderr, "not enough arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	char *plug_addr = argv[1]; | ||||
| 	char *ssid = argv[3]; | ||||
| 	char *password = argv[4]; | ||||
| 	char *key_type = argv[5]; | ||||
| 
 | ||||
| 	errno = 0; | ||||
| 	char *endptr; | ||||
| 	int key_type_num = (int)strtol(key_type, &endptr, 10); | ||||
| 	if(errno || endptr == key_type) { | ||||
| 		fprintf(stderr, "invalid key type: %s\n", key_type); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	const char *template = | ||||
| 		"{\"netif\":{\"set_stainfo\":{\"ssid\":\"%s\",\"password\":" | ||||
| 		"\"%s\",\"key_type\":%d}}}"; | ||||
| 
 | ||||
| 	size_t len = snprintf(NULL, 0, template, ssid, password, | ||||
| 				key_type_num); | ||||
| 	len++;	// snprintf does not count the null terminator
 | ||||
| 
 | ||||
| 	char *msg = calloc(1, len); | ||||
| 	snprintf(msg, len, template, ssid, password, key_type_num); | ||||
| 
 | ||||
| 	char *response = hs100_send(plug_addr, msg); | ||||
| 
 | ||||
| 	return response; | ||||
| } | ||||
| 
 | ||||
| char *handler_set_server(int argc, char *argv[]) | ||||
| { | ||||
| 	if(argc < 4) { | ||||
| 		fprintf(stderr, "not enough arguments\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	char *plug_addr = argv[1]; | ||||
| 	char *server = argv[3]; | ||||
| 
 | ||||
| 	const char *template = | ||||
| 		"{\"cnCloud\":{\"set_server_url\":{\"server\":\"%s\"}}}"; | ||||
| 
 | ||||
| 	size_t len = snprintf(NULL, 0, template, server); | ||||
| 	len++;	// snprintf does not count the null terminator
 | ||||
| 
 | ||||
| 	char *msg = calloc(1, len); | ||||
| 	snprintf(msg, len, template, server); | ||||
| 
 | ||||
| 	char *response = hs100_send(plug_addr, msg); | ||||
| 
 | ||||
| 	return response; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| struct cmd_s { | ||||
| 	char *command; | ||||
| 	char *help; | ||||
| @ -13,11 +73,22 @@ struct cmd_s { | ||||
| 	int end; | ||||
| }; | ||||
| struct cmd_s cmds[] = { | ||||
| 	{ | ||||
| 		.command = "associate", | ||||
| 		.help = "associate <ssid> <key> <key_type>\n" | ||||
| 			"\t\t\tset wifi AP to connect to", | ||||
| 		.handler = handler_associate, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.command = "factory-reset", | ||||
| 		.help = "factory-reset\treset the plug to factory settings", | ||||
| 		.json = "{\"system\":{\"reset\":{\"delay\":0}}}", | ||||
| 	}, | ||||
| 	{ | ||||
| 		.command = "info", | ||||
| 		.help = "info\t\tget device info", | ||||
| 		.json = "{\"system\":{\"get_sysinfo\":{}}}", | ||||
| 	}, | ||||
| 	{ | ||||
| 		.command = "off", | ||||
| 		.help = "off\t\tturn the plug on", | ||||
| @ -39,6 +110,12 @@ struct cmd_s cmds[] = { | ||||
| 			" GHz ones)", | ||||
| 		.json = "{\"netif\":{\"get_scaninfo\":{\"refresh\":1}}}", | ||||
| 	}, | ||||
| 	{ | ||||
| 		.command = "set_server", | ||||
| 		.help = "set_server <url>\n" | ||||
| 			"\t\t\tset cloud server to <url> instead of tplink's", | ||||
| 		.handler = handler_set_server, | ||||
| 	}, | ||||
| 	{ | ||||
| 		.end = 1, | ||||
| 	}, | ||||
| @ -68,29 +145,27 @@ void print_usage() | ||||
| 	int cmds_index = 0; | ||||
| 	while(!cmds[cmds_index].end) | ||||
| 	{ | ||||
| 		fprintf(stderr, "\t%s\n", cmds[cmds_index].help); | ||||
| 		fprintf(stderr, "\t%s\n\n", cmds[cmds_index].help); | ||||
| 		cmds_index++; | ||||
| 	} | ||||
| 	fprintf(stderr, "\n" | ||||
| 			"Report bugs to https://github.com/jkbenaim/hs100\n" | ||||
| 	); | ||||
| 	fprintf(stderr, "Report bugs to https://github.com/jkbenaim/hs100\n"); | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
| 	if(argc != 3) { | ||||
| 	if(argc < 3) { | ||||
| 		print_usage(); | ||||
| 		return 1; | ||||
| 	} | ||||
| 	char *plug_addr = argv[1]; | ||||
| 	char *cmd_string = argv[2]; | ||||
| 	char *response; | ||||
| 	char *response = NULL; | ||||
| 
 | ||||
| 	struct cmd_s *cmd = get_cmd_from_name(cmd_string); | ||||
| 	if(cmd != NULL) { | ||||
| 		if(cmd->handler != NULL) | ||||
| 			response = cmd->handler(argc, argv); | ||||
| 		else | ||||
| 		else if(cmd->json != NULL) | ||||
| 			response = hs100_send(plug_addr, cmd->json); | ||||
| 	} else { | ||||
| 		// command not recognized, so send it to the plug raw
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user