Link Search Menu Expand Document

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