Thursday, March 26, 2015

XBOX 360 monitoring

XBOX 360 is great even it's "old" already compared to XBOX One and other next gen consoles. Never the less I like XBOX 360 even though I'm missing few thinks (limited USB stack implementation, missing Wake On LAN).

However I've decided I shall monitor my entertaining systems to be able switch off AV reciever or Display if forget to. For this I need to know if my Xbox 360, PC or DVB-T is running.... I'll cover this "auto switch off system" in another post.

During my exploration I find following problems:
  1. ping is not the option, XBOX 360 doesn't reply to ICMP request
  2. UPnP is running only when not playing game
  3. arping works only with IP, if only MAC address is provide it will send request with broadcast IP which xbox will not respond
So the solution is to set for XBOX fixed IP and use:
  1. arping to verify if device is up
  2. gssdp-discovery to check if game is running (and get UPnP Port if not)

Below is script using arping to verify if device is up and if so then find what UPnP port is it listening(if game is not played), results are stored in sqlite db for purpose of further use

#! /bin/bash


#test ICMP connectivity with ping
testARPing()
{
  return `arping -c 4 $1 | grep "100% unanswered" | wc -l`
}

XBOXIP='10.0.0.41'
XBOXMAC='7c:1e:52:c2:6c:a7'
XBOXUUID='03166842-2743-2000-0000-7c1e52c26ca7'

DBFILE='/var/www/judo.db'

if `testARPing $XBOXIP`
  then
    new_status="Up"
    location=`gssdp-discover -n 10 -t uuid:$XBOXUUID | grep "Location:" | sed 's/ *Location: http:\/\///g'| cut -d/ -f1 | sed 's/\///g'`
    #echo "$location"
    #ip=$(echo "$location" | cut -d: -f1)
    upnp_port=$(echo "$location" | cut -d: -f2)
  else
    new_status="Down"
fi

new_polls=1
prev_status_polls=$(sqlite3 $DBFILE "SELECT cur_state,polls_in_state FROM dev_status WHERE mac = '$XBOXMAC';")
prev_status=$(echo "$prev_status_polls" | cut -d\| -f1)
prev_polls=$(echo "$prev_status_polls" | cut -d\| -f2)
if [ "$prev_status" == "$new_status" ]
then
  new_polls=$((prev_polls + 1))
fi
sqlite3 $DBFILE "UPDATE dev_status SET cur_state = '$new_status', polls_in_state = '$new_polls' WHERE mac = '$XBOXMAC';"
sqlite3 $DBFILE "UPDATE devices SET upnp_port = '$upnp_port' WHERE mac = '$XBOXMAC';"
echo "$XBOXIP,$XBOXMAC,$new_status,$prev_status,$new_polls"

Tuesday, March 17, 2015

Home printer monitoring - Brother DCP-J4110DW

As I'm trying to automate and monitor everything in my home I wanted to monitor my printer/scanner, Brother DCP-J4110DW.

First thing I did, and I do with every device I have, here is what I find.
21/tcp   open  ftp -
220 FTP print service:V-1.13/Use the network password for the ID if updating.
Name (10.0.0.39:pi): admin
23/tcp   open  telnet - Doesn't ask for anything(no request for user or password, no command-line)
25/tcp   open  smtp
80/tcp   open  http - Web Management and setting
443/tcp  open  https -  Web Management and setting
515/tcp  open  printer
631/tcp  open  ipp
9100/tcp open  jetdirect

Second thing is snmpwalk with community public and in this case it works (even I didn't find snmp agent setting in printer configuration). I've tried to find following statistics:
    Total Pages printed - iso.3.6.1.2.1.43.10.2.1.4.1.1 = Counter32: 115
    Monochromatic pages - iso.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.52.1.1.3.3 = Counter32: 17
    Color pages - iso.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.52.1.1.3.4 = Counter32: 98

I was not successful to get ink level, even though the OIDs for those are present the value given is 'Unknown', most probably this is only implemented on printers targeted for companies.
However I'm able to see the ink level on status webpage (status webpages is accessible without login which is fine and easier to get statistics).
The html code we need to get info from is looking like this below and ink level is actually the height of the color image.
<div id="ink_level">
<table id="inkLevel" summary="ink level">
<tr><th></th><th></th><th></th><th><img src="../common/images/low.gif" alt="Low" /></th></tr><tr>
<td><img src="../common/images/magenta.gif" alt="Magenta" class="tonerremain" height="23px" /></td>
<td><img src="../common/images/cyan.gif" alt="Cyan" class="tonerremain" height="18px" /></td>
<td><img src="../common/images/yellow.gif" alt="Yellow" class="tonerremain" height="16px" /></td>
<td><img src="../common/images/black.gif" alt="Black" class="tonerremain" height="9px" /></td>
</tr><tr><th>M</th><th>C</th><th>Y</th><th>BK</th></tr>
</table>
</div>

So I wrote following code in python (Brother_inkLevel) to get the ink level and provide in text output which would be easy to parse by other scripts Brother_inkLevel.py


#! /usr/bin/python

import sys
import httplib, urllib
import re
from xml.dom import minidom
from xml.parsers.expat import ExpatError

#get status html
url = 'http://10.0.0.39/general/status.html'
html = urllib.urlopen(url).read()

inkLevel = ''

#parse hmtl
#get all img tags
#if it's inklevel img I get the height, it's represent the ink level
xmldoc = minidom.parseString(html)
xml_images = xmldoc.getElementsByTagName('img')
for img in xml_images:
  if img.getAttribute('alt') == 'Cyan':
    c = "C:" + img.getAttribute('height') + " "
  elif img.getAttribute('alt') == 'Magenta':
    m = "M:" + img.getAttribute('height') + " "
  elif img.getAttribute('alt') == 'Yellow':
    y = "Y:" + img.getAttribute('height') + " "
  elif img.getAttribute('alt') == 'Black':
    k = "K:" + img.getAttribute('height') + " "

inkLevel = c + m + y + k
print inkLevel


And here is the output of the script
root@raspberrypi:/var/www/monitoring# ./Brother_inkLevel.py
C:18px M:23px Y:16px K:9px

Next I used bash script to get printed page statistics, include ink Level and store it in sqlite db
#! /bin/bash

BROTHER_IP='10.0.0.39'
UUID='e3248000-80ce-11db-8000-30055c1cd6d3'
COMMUNITY='public'

DBFILE='/var/www/judo.db'
RD='/var/www/monitoring'

DATE=`date +%Y-%m-%d`

MONO_PAGE_OID='.1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.52.1.1.3.3'
COLOR_PAGE_OID='.1.3.6.1.4.1.2435.2.3.9.4.2.1.5.5.52.1.1.3.4'
TOTAL_PAGE_OID='.1.3.6.1.2.1.43.10.2.1.4.1.1'

MONO_PAGE_COUNT=`/usr/bin/snmpget -v 2c -c $COMMUNITY $BROTHER_IP $COLOR_PAGE_OID | awk '{print $4}'`
COLOR_PAGE_COUNT=`/usr/bin/snmpget -v 2c -c $COMMUNITY $BROTHER_IP $MONO_PAGE_OID | awk '{print $4}'`
TOTAL_PAGE_COUNT=`/usr/bin/snmpget -v 2c -c $COMMUNITY $BROTHER_IP $TOTAL_PAGE_OID | awk '{print $4}'`

echo "Monochromatic pages: $MONO_PAGE_COUNT, Color pages: $COLOR_PAGE_COUNT, Total pages: $TOTAL_PAGE_COUNT"

INKLEVEL=`$RD/Brother_inkLevel.py | sed 's/px/,/g;' | sed 's/C://g;' | sed 's/M://g' | sed 's/Y://g;' | sed 's/K://g;' | sed 's/, $//g;'`

echo "$INKLEVEL"

sqlite3 $DBFILE "INSERT INTO Brother_Daily_Stats VALUES('$UUID', '$DATE', $TOTAL_PAGE_COUNT, $MONO_PAGE_COUNT, $COLOR_PAGE_COUNT, $INKLEVEL);"

I've let that run for few days and bellow are results, however to get more relevant info I'll be monitoring for one year and update here more findings.
sqlite> select * from Brother_Daily_Stats;
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-21|137|119|18|18|23|16|9
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-22|137|119|18|18|23|16|9
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-23|137|119|18|18|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-24|137|119|18|18|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-25|137|119|18|18|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-26|137|119|18|18|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-27|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-02-28|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-01|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-02|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-03|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-04|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-05|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-06|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-07|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-08|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-09|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-10|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-11|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-12|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-13|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-14|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-15|137|119|18|17|23|16|8
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-16|137|119|18|13|19|11|7
e3248000-80ce-11db-8000-30055c1cd6d3|2015-03-17|137|119|18|13|18|11|5