Advertisement
Guest User

oled-esxi.py

a guest
Aug 24th, 2019
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.77 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # oled-esxi.py - Polls ESXi host for health / utilisation and displays it on a SSD1322 256x64 OLED display
  4. # Designed for use with https://forums.aida64.com/topic/4479-sale-er-oledm032-ssd1322-32-oled-usb-interface/
  5. # Written by SnarlingFox 20190824
  6.  
  7. # Import GPIO and FT232H modules.
  8. from luma.core.interface.serial import spi
  9. from luma.core.render import canvas
  10. from luma.oled.device import ssd1322
  11. from PIL import ImageFont
  12. import Adafruit_GPIO as GPIO
  13. import Adafruit_GPIO.FT232H as FT232H
  14.  
  15. from os.path import getmtime
  16. from pyVim.connect import SmartConnect
  17. from decimal import Decimal
  18. import os, time, sys, ssl
  19.  
  20. WATCHED_FILES_MTIMES = [(__file__, getmtime(__file__))]
  21.  
  22. # Connect to OLED FTDI device
  23. class FTDI_WRAPPER_SPI( FT232H.SPI ):
  24.     # This class wrapper implements the missing attributes required by the luma core interface
  25.         def writebytes(self, data):
  26.             self.write(data)
  27.  
  28.         def open(self, port, device):
  29.             # Do nothing
  30.             a=1
  31.  
  32. FT232H.use_FT232H()      # Temporarily disable the built-in FTDI serial driver on Mac & Linux platforms.
  33. ft232h = FT232H.FT232H() # Create an FT232H object that grabs the first available FT232H device found.
  34.  
  35. # Pins initialization
  36. CS = 3     #D3 Brown
  37. RESET = 13 #C5 Purple
  38. DC = 14    #C6 White
  39.  
  40. serial = FTDI_WRAPPER_SPI(ft232h, cs=CS, max_speed_hz=8000000)
  41. ft232h_gpio = ft232h
  42. SPI = spi(spi=serial, gpio=ft232h_gpio, gpio_DC=DC, gpio_RST=RESET)
  43. device = ssd1322(SPI, rotate=0)
  44. device.persist = False
  45.  
  46. # Set up some graphical helpers
  47. def draw_gauge_percentage (canvas, x0, y0, x1, y1, percentage, legend = ""):
  48.     x1 = x0 + x1
  49.     y1 = y0 + y1
  50.     gap_degrees = 60
  51.     line_width = 5
  52.     line_height = 10
  53.     bezel_thickness = 2
  54.     if percentage < 0: percentage = 0
  55.     if percentage > 100: percentage = 100
  56.     start_position = -270 + (gap_degrees / 2)
  57.     end_position   =   90 - (gap_degrees / 2)
  58.     percentage_start_position = start_position + ((end_position - start_position) * (0.01 * percentage)) - (line_width / 2)
  59.     percentage_end_position   = start_position + ((end_position - start_position) * (0.01 * percentage)) + (line_width / 2)
  60.     canvas.pieslice(
  61.         [x0, y0, x1, y1],
  62.         start_position,
  63.         end_position,
  64.         fill="#fff"
  65.     )
  66.     canvas.ellipse(
  67.         [x0 + bezel_thickness, y0 + bezel_thickness, x1 - bezel_thickness, y1 - bezel_thickness],
  68.         fill="#000", width=0
  69.     )  
  70.     canvas.pieslice(
  71.         [x0 + bezel_thickness, y0 + bezel_thickness, x1 - bezel_thickness, y1 - bezel_thickness],
  72.         percentage_start_position,
  73.         percentage_end_position,
  74.         fill="#999"
  75.     )
  76.     canvas.ellipse(
  77.         [x0 + line_height, y0 + line_height, x1 - line_height, y1 - line_height],
  78.         fill="black", width=0
  79.     )
  80.     textsize = canvas.textsize(legend)
  81.     legend_offset_x = x0 + ((x1-x0-textsize[0])/2)
  82.     legend_offset_y = y0 + ((y1-y0-textsize[1])/2) + 1
  83.     canvas.text([legend_offset_x, legend_offset_y], legend)
  84.  
  85. def draw_bargraph_horizontal_percentage (canvas, x0, y0, x1, y1, percentage, legend = ""):
  86.     x1 = x0 + x1
  87.     y1 = y0 + y1
  88.     if percentage < 0: percentage = 0
  89.     if percentage > 100: percentage = 100
  90.     canvas.rectangle([x0, y0, x1, y1], outline=None, fill="#333")
  91.     canvas.rectangle([x0, y0, x0 + ((x1 - x0) * (0.01 * percentage)), y1], outline=None, fill="#777")
  92.     canvas.rectangle([x0, y0, x1, y1], outline="#fff", fill=None)
  93.     textsize = canvas.textsize(legend)
  94.     legend_offset_x = x0 + ((x1-x0-textsize[0])/2)
  95.     legend_offset_y = y0 + ((y1-y0-textsize[1])/2)
  96.     canvas.text([legend_offset_x, legend_offset_y], legend)
  97.  
  98. def draw_bargraph_vertical_percentage (canvas, x0, y0, x1, y1, percentage, legend = ""):
  99.     x1 = x0 + x1
  100.     y1 = y0 + y1
  101.     if percentage < 0: percentage = 0
  102.     if percentage > 100: percentage = 100
  103.     canvas.rectangle([x0, y0, x1, y1], outline=None, fill="#333")
  104.     canvas.rectangle([x0, y1 - ((y1 - y0) * (0.01 * percentage)), x1, y1], outline=None, fill="#777")
  105.     canvas.rectangle([x0, y0, x1, y1], outline="#fff", fill=None)
  106.     textsize = canvas.textsize(legend)
  107.     legend_offset_x = x0 + ((x1-x0-textsize[0])/2)
  108.     legend_offset_y = y0 + ((y1-y0-textsize[1])/2)
  109.     canvas.text([legend_offset_x, legend_offset_y], legend)
  110.  
  111. def draw_label (canvas, x0, y0, x1, y1, legend = ""):
  112.     x1 = x0 + x1
  113.     y1 = y0 + y1
  114.     textsize = canvas.textsize(legend)
  115.     legend_offset_x = x0 + ((x1-x0-textsize[0])/2)
  116.     legend_offset_y = y0 + ((y1-y0-textsize[1])/2)
  117.     canvas.text([legend_offset_x, legend_offset_y], legend)
  118.  
  119. # Connect to ESXi
  120. s = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
  121. s.verify_mode = ssl.CERT_NONE
  122. c = SmartConnect(host="HIDDEN", user="HIDDEN", pwd='HIDDEN', sslContext=s)
  123.  
  124. print "Connection to FTDI OLED and ESXi successful, sending output to OLED.."
  125.  
  126. # Main loop starts here
  127. while True:
  128.     # Poll ESXi usage summary
  129.     summary = c.content.rootFolder.childEntity[0].hostFolder.childEntity[0].summary
  130.     cpuInfo = c.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0].hardware.cpuInfo
  131.     cpuCapacity = (cpuInfo.hz * cpuInfo.numCpuCores) / 1000 / 1000
  132.     memCapacity = summary.effectiveMemory / 1024 / 1024
  133.     currentStats = c.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0].summary.quickStats
  134.     cpuUtilPercent = int((100 / float(cpuCapacity)) * float(currentStats.overallCpuUsage))
  135.     memUtilPercent = int((100 / float(memCapacity)) * float(currentStats.overallMemoryUsage))
  136.  
  137.     # Poll ESXi hardware sensors
  138.     sensors = dict()
  139.     for sensor in c.content.rootFolder.childEntity[0].hostFolder.childEntity[0].host[0].runtime.healthSystemRuntime.systemHealthInfo.numericSensorInfo:
  140.         if sensor.sensorType != 'temperature' and sensor.sensorType != 'fan': continue
  141.         sensors[sensor.name] = Decimal(int(sensor.currentReading)).shift(sensor.unitModifier)
  142.         # print sensor.name, ':', sensors[sensor.name], sensor.baseUnits
  143.  
  144.     with canvas(device) as draw:
  145.         # Blank screen
  146.         draw.rectangle(device.bounding_box, outline="black", fill="black")
  147.        
  148.         # Draw CPU and mem
  149.         draw.rectangle([0,0,76,63], outline="#fff", fill="black")
  150.         draw.rectangle([0,0,76,15], outline="#fff", fill="#555")
  151.         draw_label(draw, 0, 0, 76, 15, "Host Usage")
  152.        
  153.         draw_gauge_percentage(draw, 4, 28, 32, 32, cpuUtilPercent, str(cpuUtilPercent) + '%')
  154.         draw_label(draw, 4, 16, 32, 12, "CPU")
  155.        
  156.         draw_gauge_percentage(draw, 40, 28, 32, 32, memUtilPercent, str(memUtilPercent) + '%')
  157.         draw_label(draw, 40, 16, 32, 12, "MEM")
  158.        
  159.         # Draw Temps
  160.         draw.rectangle([80,0,175,63], outline="#fff", fill="black")
  161.         draw.rectangle([80,0,175,15], outline="#fff", fill="#555")
  162.         draw_label(draw, 80, 0, 95, 15, "Temperatures")
  163.        
  164.         i = 0 ; i_step = 11 ; j = 0
  165.         for sensor in sensors:
  166.             if 'cpu' in sensor.lower():
  167.                 draw_bargraph_horizontal_percentage(draw, 83, 18 + i, 89, i_step - 2, int((100 / float(85)) * float(sensors[sensor])), "CPU" + str(j) + " " + str(sensors[sensor]) + "'C")
  168.                 i += i_step; j += 1
  169.        
  170.         draw_bargraph_horizontal_percentage(draw, 83, 18 + i, 89, i_step - 2, int((100 / float(85)) * float(sensors['System Board 2 Peripheral Temp'])), "Mobo " + str(sensors['System Board 2 Peripheral Temp']) + "'C")
  171.         i += i_step; j += 1
  172.         draw_bargraph_horizontal_percentage(draw, 83, 18 + i, 89, i_step - 2, int((100 / float(85)) * float(sensors['System Board 1 System Temp'])), "Case " + str(sensors['System Board 1 System Temp']) + "'C")
  173.        
  174.         # Draw Fans
  175.         draw.rectangle([179,0,255,63], outline="#fff", fill="black")
  176.         draw.rectangle([179,0,255,15], outline="#fff", fill="#555")
  177.         draw_label(draw, 179, 0, 76, 15, "Case Fans")
  178.        
  179.         i = 0 ; i_step = 9 ; j = 0
  180.         for sensor in sensors:
  181.             if 'fan' in sensor.lower():
  182.                 draw_bargraph_vertical_percentage(draw, 182 + i, 28, i_step - 2, 32, int((100 / float(2000)) * float(sensors[sensor])))
  183.                 draw_label(draw, 182 + i, 17, i_step + 1, 12, str(j))
  184.                 i += i_step; j += 1
  185.  
  186.     time.sleep(3)
  187.    
  188.     # Check if we were modified and exit so we can be reloaded
  189.     for f, mtime in WATCHED_FILES_MTIMES:
  190.         if getmtime(f) != mtime:
  191.             sys.exit(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement