@nodecentral , @datamonkey , thanks for your suggestions.
@datamonkey , while your approach may also work I already started to make modifications yesterday and have reached the solution explained below. So here are the changes to the first post:
Update to 2 devices and manual disconnection
Ok, so what I try to accomplish is summarized in the card shown in the next figure. The red box joins the elements needed to make a programmed control of the disconnection while the blue one corresponds to the manual (and immediate) disconnection/connection.
Let’s start explaining this card, which is saved, in my case, in .homeassistant/includes/groups/internet_control.yaml:
internet:
name: 'Internet'
control: hidden
entities:
- automation.disconnect_ipad_1_prog
- automation.disconnect_ipad_2_prog
- input_slider.internet_cut_time
- input_slider.internet_cut_hour
- input_slider.internet_cut_minutes
- sensor.internetcuttime
- switch.internet_ipad1
- switch.internet_ipad2
It consists of the same three input_sliders explained earlier in this post and have not been modified. The sensor created to easily visualize the moment when the disconnection will happen remains the same, too.
The first two elements of the card is the automation for the programmed disconnection. Keep in mind that it is an automation with configurable starting and duration times on the fly; so no need to restart HA when re-programming the disconnection. I have these two entries in my automations.yaml file:
- id: id031
alias: 'Disconnect iPad 1 (prog)'
trigger:
platform: time
minutes: '/5'
seconds: '0'
condition:
condition: template
value_template: '{{ ((now().strftime("%s") | int ) | timestamp_custom("%H:%M")) == states.sensor.internetcuttime.state }}'
action:
- service: shell_command.cut_internet_ipad1
- id: id032
alias: 'Disconnect iPad 2 (prog)'
trigger:
platform: time
minutes: '/5'
seconds: '0'
condition:
condition: template
value_template: '{{ ((now().strftime("%s") | int ) | timestamp_custom("%H:%M")) == states.sensor.internetcuttime.state }}'
action:
- service: shell_command.cut_internet_ipad2
Programmed Internet disconnection can be applied to one or both devices. With the current setup only one program per day is allowed and, if both devices are activated, they will run with the same timing settings.
As in my previous post, the automation calls a shell_command that is in the file .homeassistant/includes/shell_commands/cut_internet.yaml and has been modified to include two devices:
cut_internet_ipad1: '/home/homeassistant/.homeassistant/includes/shell_scripts/control_internet.sh DE:VI:CE:ONE:MAC {{ states.input_slider.internet_cut_time.state }}'
cut_internet_ipad2: '/home/homeassistant/.homeassistant/includes/shell_scripts/control_internet.sh DE:VI:CE:TWO:MAC {{ states.input_slider.internet_cut_time.state }}'
which calls a complete renewed bash script with two arguments: MAC and programmed disconnection time. I have the bash scripts stored in .homeassistant/includes/shell_scripts folder and the file control_internet.sh is now:
#!/bin/bash
# Examples:
# Activate spoofing given a MAC address
# ./control_internet AA:BB:CC:DD:EE:FF on
# Deactivate spoofing given a MAC address
# ./control_internet AA:BB:CC:DD:EE:FF off
# Activate spoofing for 10 minutes given a MAC address
# ./control_internet AA:BB:CC:DD:EE:FF 10
CHILD_MAC=$1
INTERFACE=eth0
ROUTER_ADRS=192.168.0.1
if [ "$2" = "on" ]
then
# Activating manual spoof
CHILD_ADRS=$(nmap -sP ${ROUTER_ADRS}/24 >/dev/null && arp -an | grep ${CHILD_MAC} | awk '{print $2}' | sed 's/[()]//g')
sudo arpspoof -i ${INTERFACE} -t ${CHILD_ADRS} ${ROUTER_ADRS} > /dev/null 2>&1 & echo $! > /tmp/manualspoof-${CHILD_MAC}.pid
elif [ "$2" = "off" ]
then
# Deactivating manual spoof
sudo pkill -P `cat /tmp/manualspoof-${CHILD_MAC}.pid`
rm /tmp/manualspoof-${CHILD_MAC}.pid
else
# Activate temporarily spoof
CUT_TIME=$2
CHILD_ADRS=$(nmap -sP ${ROUTER_ADRS}/24 >/dev/null && arp -an | grep ${CHILD_MAC} | awk '{print $2}' | sed 's/[()]//g')
sudo arpspoof -i ${INTERFACE} -t ${CHILD_ADRS} ${ROUTER_ADRS} > /dev/null 2>&1 & echo $! > /tmp/progspoof-${CHILD_MAC}.pid
sleep ${CUT_TIME}m
sudo pkill -P `cat /tmp/progspoof-${CHILD_MAC}.pid`
rm /tmp/progspoof-${CHILD_MAC}.pid
fi
When the second argument is not “on” or “off” we assume that it is the programmed disconnection time (in minutes) and the else part of the script is run. This part is very similar to the script posted initially with some modifications to retrieve the PID of the arpspoof process, saving it in a temp file in order to kill the process when the disconnection time passes. What about the “on” or “off” conditions? Keep on reading.
The two last switches in the card account for manual (and instantaneous) disconnection as @datamonkey suggested. They are command line switches that I place in .homeassistant/includes/switches/manual_control_internet.yaml and contains:
# Internet manual disconnect switches
- platform: command_line
switches:
internet_ipad1:
command_on: "/home/homeassistant/.homeassistant/includes/shell_scripts/control_internet.sh DE:VI:CE:ONE:MAC on"
command_off: "/home/homeassistant/.homeassistant/includes/shell_scripts/control_internet.sh DE:VI:CE:ONE:MAC off"
friendly_name: Disconnect iPad 1 (manual)
- platform: command_line
switches:
internet_ipad2:
command_on: "/home/homeassistant/.homeassistant/includes/shell_scripts/control_internet.sh DE:VI:CE:TWO:MAC on"
command_off: "/home/homeassistant/.homeassistant/includes/shell_scripts/control_internet.sh DE:VI:CE:TWO:MAC off"
friendly_name: Disconnect iPad 2 (manual)
As you can observe each switch uses one MAC and calls the bash script commented before but in this case the second argument is “on” or “off”; to active the spoofing or stop it. Again, we save the PID information to a temp file in order to know which process we have to kill.
If we want to have a toogle switch in the frontend and not two separate lighting bolt icons, we have to add to our customization file this:
switch.internet_ipad1:
assumed_state: false
switch.internet_ipad2:
assumed_state: false
Extrapolation to more devices should be straightforward since no modification to the bash script is needed; just add the elements in the frontend and make slight modifications to the corresponding files. I have tested it and it works for me, although maybe there are combinations that I haven’t tried. Thanks for reading.