SWITCH AUTOMATION
The requirements for the automation to work are that the switch:
- is manageable
- is accessible through a CLI
- provides PoE
The automation is programmed in Bash scripts using Expect encapsulated in a python program. The instructions below are based for a Cisco 250 Smart Switch and run in a linux setup, for other switches the commands may be different, but the strategy should be similar.
1. Set up SSH:
- Create a key in your “master” device and copy it.
- Add your key to your switch. In the Cisco system you do that under: Security > SSH Server > SSH User Authentication > Add the key to SSH User Authentication Table (by Public Key) and enable SSH User Authentication by Public Key and automatic login (For seeing these options you have to change the view to Advanced)
2. Install needed dependencies:
- Expect
$apt-get install expect
- Python and pip if not already installed.
- Python MQTT package if using MQTT for monitoring solar
$pip3 install paho-mqtt
3. Create expect scripts:
Once the SSH connection between the “master” device and the switch is setup, expect scripts can be used for simulating a CLI interaction.
set timeout 20
set IPaddress xxx.xxx.x.xxx //IP adress of Switch
spawn ssh -oHostKeyAlgorithms=+ssh-dss user@$IPaddress
expect "#"
send "config\r"
expect "(config)#"
#
send "interface GE[lindex $argv 0]\r"
expect "(config-if)#"
send "power inline auto\r"
expect "(config-if)#"
send "end\r"
expect "#"
send "exit\r"
sleep 1
exit
A similar script is used for turning off but changing one line (this could be added as an argument instead): send "power inline never\r"
Once the scripts are created they can be activated with the port as argument $expect script_name.exp portnumber
4. Create Python script
Once the expect scripts are set up, the next step is to create a python script that monitors the solar system and adapt the cluster based on that information using the created scripts. The script also saves information about the status and solar production in json files for using in the website.
The script has a count flag so it doesn’t automatically change status when solar production changes, but it delays using a counter until it is assured that the change is
# Libraries to add
import paho.mqtt.client as mqtt
import json
import os
import subprocess
# Global variables:
kw_out = 0
flag = 1
# Time flags for controlling updating
counter = 0
time_counter = 0
# Function that counts up when solar is producing to change status
def increase():
global counter
global flag
if counter < 20:
counter +=1
print("Increased counter")
else:
counter = 0
flag = 1
start3()
print("Started")
# Function that counts up when solar is down to change status
def decrease():
global counter
global flag
if counter < 20:
counter +=1
print("Decreased counter")
else:
counter = 0
flag = 0
stop3()
print("Stopped")
# Start cluster and change status (in this case all the devices except master)
def start3():
os.system('expect /home/pi/control/start.exp 2')
os.system('expect /home/pi/control/start.exp 3')
os.system('expect /home/pi/control/start.exp 4')
dictionary = {"status": 1,}
with open("/var/www/cellar/status.json", "w") as outfile:
json.dump(dictionary, outfile)
# Stop cluster and change status (in this case all the devices except master)
def stop3():
dictionary = {"status": 0,}
with open("/var/www/cellar/status.json", "w") as outfile:
json.dump(dictionary, outfile)
os.system('expect /home/pi/control/stop.exp 2')
os.system('expect /home/pi/control/stop.exp 3')
os.system('expect /home/pi/control/stop.exp 4')
# reads energy consumption from switch using expect to a json
def read_energy():
output = subprocess.check_output("expect /home/pi/control/energy.exp | cut -c 32-33", shell=True)
watt = output.decode("utf-8")
watt = watt[:-1]
print(watt)
dictionary = {
"w": watt,
}
with open("/var/www/cellar/energy.json", "w") as outfile:
json.dump(dictionary, outfile)
# saves kw_out in json
def update_kw():
global kw_out
global flag
global time_counter
print(kw_out)
print(flag)
if (time_counter == 15):
read_energy()
time_counter = 0
else:
time_counter += 1
print(time_counter)
if kw_out > 0 and flag == 0:
increase()
if kw_out == 0 and flag == 1:
decrease()
dictionary = {
"kw_out": kw_out,
}
with open("/var/www/cellar/kwh.json", "w") as outfile:
json.dump(dictionary, outfile)
# the callback function, it will be triggered when receiving messages
def on_message_minus(client, userdata, msg):
global kw_out
kw_out =float(msg.payload)
update_kw()
# Connect to MQTT
def on_connect(client, userdata, flags, rc):
# subscribe, which need to put into on_connect
client.subscribe("") #Update to add
client.message_callback_add('', on_message_minus)
# Reconnect
def reconnect_mqtt():
global client
client.loop_stop()
client.username_pw_set("user", "password")
client.connect("server", port, 60)
client.loop_forever()
#Set upp MQTT connection
client = mqtt.Client()
client.on_connect = on_connect
# create connection, the three parameters are broker address, broker port number, and keep-alive time respectively
client.username_pw_set("user", "password")
client.connect("server", port, 60)
# set the network loop blocking, it will not actively end the program before calling disconnect() or the program crash
client.loop_forever()
5. Create service
The last step is to add the above python script to a service so it is run in the background by the system.
[Unit]
Description=launch solar kwh monitoring
After=network.target
[Service]
Type=idle
SyslogIdentifier=SampleService
Environment="DISPLAY=:0"
ExecStart=/usr/bin/python3 filelocation
Restart=on-failure
RestartSec=30
User=youruser
[Install]
WantedBy=multi-user.target