Using SNMP MIB Data to Capture Ink Levels

mibb-traceMy regular readers know that I have implemented an extensive home automation system that allows full control and automation of everything from doors to lights to fireplaces to full multi-zone temperature management and includes various tracking and reporting functionality. One of the items that I’ve been tracking for years is the level of ink in the family printer.  When the level gets low, it sends emails to my wife and myself to remind us to change and, if necessary, purchase new cartridges.  That functionality has been working just fine since 2011. About two weeks ago we started having problems with our printer. The issue turned out to be the print head.  Unfortunately replacement parts were almost as much as a new printer so I opted to toss the old machine and buy a new one.

The system I had devised for pulling data off the old printer involved screen-scraping data off of the printer’s built-in web server. I was hoping my scripts would continue to work with the new printer but they didn’t.  Rather than resort to screen-scraping again, I thought I would look for an API so I could pull the data “correctly” and process it into my home automation system.  A bit of searching didn’t turn up anything very promising so I thought I would look at SNMP. I quickly found that OS/X has an snmpInk command that ships as part of it’s Developer Library. Since my old script ran on my Mac Server, and the updated script will run in its place, this was a good fit.

Since the SNMP MIB data doesn’t report a percentage of the cartridge used or a percentage of the cartridge available as my old system did, I needed to get a bit more creative. The OIDs that were available to me were prtMarkerSuppliesMaxCapacity and prtMarkerSuppliesLevel. With this data I’m able to quickly calculate the amount if ink available in each cartridge and then update the appropriate variables in my home automation system via web services.

#!/usr/bin/php -q
<?php 
/** 
*  Author: Geek-Tips 
*    Date: 15 December 2013 
* Updated: 
*    File: printer.php 
* Version: 0.03 
* Purpose: This is the printer module for my Domotica solution.  The scripts purpose is to capture 
*          ink level information from the printer and post it to Indigo. 
* 
*   Notes: v0.03: Changed script to use snmpInk as data source. 
*          v0.02: Added test condition for printer availability. If the printer is off then the 
*                 program exits rather than updating the variables with blank data. 
*          v0.01: This is version 0.1 of the printer script. 
* 
*   Usage: printer.php 
* 
*   Kudos: This URL was helpful - http://www.phpro.org/examples/Parse-HTML-With-PHP-And-DOM.html 
* 
*   Legal: The contents of this file belong to Geek-Tips and may not be modified, copied or otherwise 
*          altered in any way without the express written consent of the author. 
*          This is a copyrighted work and ALL rights are reserved. 
*
*/ 

date_default_timezone_set('America/Chicago'); 
$indigourl = "http://127.0.0.1/modvars/"; 
$raw = shell_exec('/System/Library/Printers/Libraries/snmpInk Photosmart_7520_series'); 
$raw = trim(preg_replace('/[\t]/', '', $raw)); 
$temp = explode("\n", $raw); if (strlen($raw) --> 0) {

//black ink :: prtMarkerSuppliesMaxCapacity - 14 :: prtMarkerSuppliesLevel - 12
$max = preg_replace("/[^0-9,.]/", "", $temp[14]);
$lvl = preg_replace("/[^0-9,.]/", "", $temp[12]);
$blk = round($lvl/$max * 100);
//yellow ink :: prtMarkerSuppliesMaxCapacity - 28 :: prtMarkerSuppliesLevel - 26
$max = preg_replace("/[^0-9,.]/", "", $temp[28]);
$lvl = preg_replace("/[^0-9,.]/", "", $temp[26]);
$yel = round($lvl/$max * 100);
//cyan ink :: prtMarkerSuppliesMaxCapacity - 42 :: prtMarkerSuppliesLevel - 40
$max = preg_replace("/[^0-9,.]/", "", $temp[42]);
$lvl = preg_replace("/[^0-9,.]/", "", $temp[40]);
$cyn = round($lvl/$max * 100);
//magenta ink :: prtMarkerSuppliesMaxCapacity - 56 :: prtMarkerSuppliesLevel - 54
$max = preg_replace("/[^0-9,.]/", "", $temp[56]);
$lvl = preg_replace("/[^0-9,.]/", "", $temp[54]);
$mag = round($lvl/$max * 100);
//light black ink :: prtMarkerSuppliesMaxCapacity - 70 :: prtMarkerSuppliesLevel - 68
$max = preg_replace("/[^0-9,.]/", "", $temp[70]);
$lvl = preg_replace("/[^0-9,.]/", "", $temp[68]);
$pto = round($lvl/$max * 100);

$dte = urlencode(date("F j, Y, g:i a"));

$updateurl = $indigourl . "pBlack?_method=put&value=" . $blk;
get_data($updateurl);

$updateurl = $indigourl . "pYellow?_method=put&value=" . $yel;
get_data($updateurl);

$updateurl = $indigourl . "pCyan?_method=put&value=" . $cyn;
get_data($updateurl);

$updateurl = $indigourl . "pMagenta?_method=put&value=" . $mag;
get_data($updateurl);

$updateurl = $indigourl . "pPhoto?_method=put&value=" . $pto;
get_data($updateurl);

$updateurl = $indigourl . "pDate?_method=put&value=" . $dte;
get_data($updateurl);
}

//Function to get the data from a URL
function get_data($url)
{
$ch = curl_init();
$timeout = 5;
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,$timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
?>

With this script in place and running, via cron, every couple of hours, the central dashboard is always up to date and we, once again, receive notifications when ink levels are low.

Until next time – GEEK OUT!

~GT~

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload the CAPTCHA.