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

Thursday, January 29, 2015

Understanding binary file

Most of DVB-Ts and TVs got channel list in file called dtv_channel.txt Of course there are tools to manipulate this file content, but most of them is for windows and I just need export the list to show it in my web customer remote controler.
We begin with hexdump, but to understand it better we convert the output to human readable ASCII and add underscore after each char to separate them for better reading using following command:

hexdump -e '"%_u\_"' dtv_channel.txt

syn_nul_so_nul_lf_nul_* 
O_c_k_o_ _G_o_l_d_nul_* 
88_fe_85_dle_h_b4_85_dle_80_V___._nul_* 
bs_nul_* 
cb_ _stx_etx_stx_eot_nul_* 
soh_nul_* 
dle_nul_ht_nul_* 
O_c_k_o_ _G_o_l_d_nul_* 
soh_etb_soh_nul_* 
soh_etb_stx_nul_* 
soh_nul_* 
stx_etb_etx_nul_e_z_c_nul_* 
ff_nul_* 
ff_nul_* 
etb_nul_si_nul_ht_nul_* 
S_l_a_g_r_ _T_V_nul_* 
dle_stx_86_dle_nul_fb_85_dle_80_V___._nul_* 
bs_nul_* 
cb_ _stx_etx_soh_syn_nul_* 
soh_nul_* 
dle_nul_bs_nul_* 
S_l_a_g_r_ _T_V_nul_* 
soh_ht_soh_nul_* 
soh_ht_stx_nul_* 
soh_nul_* 
stx_ht_etx_nul_e_z_c_nul_* 
ff_nul_* 
ff_nul_* 
can_nul_dle_nul_bel_nul_* 
A_C_T_I_V_E_nul_* 
88_fe_85_dle_80_V___._nul_* 
bs_nul_* 
cb_ _stx_etx_soh_fs_nul_* 
soh_nul_* 
dle_nul_ack_nul_* 
A_C_T_I_V_E_nul_* 
soh_nak_soh_nul_* 
soh_nak_stx_nul_* 
soh_nul_* 
stx_nak_etx_nul_e_z_c_nul_* 
ff_nul_* 
ff_nul_*
After closer look we can see that there is clear record separator (we can divide to rows)
ff_nul_* 
ff_nul_*
Another think we can see is each "line" ends with nul_* in fact this in the reality it's more nuls. Some file formats use fix length for filed and if data is shorter it's filled with nuls which is this case.

So let's expect that nul* is field separator. Also there are lines containing bs_nul_* and soh_nul_* and they repeat in pattern, so most probably this is also some kind of separator.

Now lets used couple of seds to get some more readable format which we can further analyze.
hexdump -e '"%_u\_"' dtv_channel.txt | sed 's/^ff_nul_\*$/;;/g' | sed 's/nul_\*/,/g' | sed 's/^soh_,$//g' | sed 's/^bs_,$//g' | while read line; do echo -n $line; done | sed 's/;;/;\n/g' | sed '/^;$/d'

Let me explain for those not familiar:
#substitute nul_* with , (comma), we will use comma as filed separator
sed 's/nul_\*/,/g'
#remove lines which contains only soh_, and bs_,
sed 's/^soh_,$//g' | sed 's/^bs_,$//g'
#now let's get all data in one single line
while read line; do echo -n $line;
#and get it separated in to lines based and add ; (semicolon) as clear record separator I used just one ff_, because I find sometimes not every two ff_ separate record (not sure why)
sed 's/,ff_,/;\n/g'

we can remove Following from begining as it's file header ack_,ff_em_,

Now this is example of output
soh_nul_soh_nul_bs_,C_T_ _1_ _J_M_,f8_c7_85_dle_,80_:_dcl_ _,cb_ _dc2_soh_*,dle_nul_bel_,C_T_ _1_ _J_M_,soh_*,soh_*stx_,stx_,dcl_soh_etx_nul_e_z_c_nul_dc3_soh_etx_,;
!_soh_*,e_z_c_,;
enq_nul_soh_nul_dle_,C_R_o_ _R_A_D_I_O_Z_U_R_N_A_L_,`_8d_85_dle_b8_83_85_dle_80_:_dcl_ _,cb_ _dc2_soh_*A_,stx_,_nul_si_,C_R_o_ _R_A_D_I_O_Z_U_R_N_A_L_,dcl_dle_,dcl_dle_etx_nul_e_z_c_,;
stx_nul_stx_nul_enq_,C_T_ _2_,80_cb_85_dle_f8_c7_85_dle_80_:_dcl_ _,cb_ _dc2_soh_stx_soh_,dle_nul_eot_,C_T_ _2_,soh_stx_soh_,soh_stx_*,stx_,dcl_stx_etx_nul_e_z_c_nul_dc3_stx_etx_,;
!_stx_soh_*,e_z_c_,;
ack_nul_stx_nul_vt_,C_R_o_ _D_V_O_J_K_A_,p_d4_85_dle_`_8d_85_dle_80_:_dcl_ _,cb_ _dc2_soh_stx_A_,stx_,_nul_lf_,C_R_o_ _D_V_O_J_K_A_,dcl_*,dcl_*etx_nul_e_z_c_,;
etx_nul_etx_nul_ack_,C_T_ _2_4_,bs_cf_85_dle_80_cb_85_dle_80_:_dcl_ _,cb_ _dc2_soh_etx_soh_,dle_nul_enq_,C_T_ _2_4_,soh_etx_soh_,soh_etx_stx_,stx_,dcl_etx_*nul_e_z_c_nul_dc3_etx_*,;
!_etx_soh_*,e_z_c_,;

we can see some shorter line like this !_stx_soh_*,e_z_c_,; if we take closer look we will find that nul_* is not always field, separator (nuls can be valid part of data).
Never the less we can remove those shorter lines for the moment or manually move them

So now we have "nice" output we can open in any spreadsheet program and parse by comma. We see that 2nd column contains Name of channel. If we elaborate more on first column we can see that nul_ separate some 3 values.

soh_nul_soh_nul_bs_
enq_nul_soh_nul_dle_
stx_nul_stx_nul_enq_
ack_nul_stx_nul_vt_
etx_nul_etx_nul_ack_
bel_nul_etx_nul_vt_
eot_nul_eot_nul_ht_
bs_nul_eot_nul_si_
ht_nul_enq_nul_lf_
cr_nul_enq_nul_ack_
lf_nul_ack_nul_dcl_
so_nul_ack_nul_ff_
1st is actually 1,5,2,6,3,7,4,8,9,13... as far as values are unique I guess this might be index
2nd values are actually sequential, but twice (1,1,2,2,3,3...) that's because there are TV's and Radios mixed together.
3rd as we can see values repeating here randomly so there is and values are: 8,16,5,11,6,11,.... this is slightly complected, but actually it's length of channel name+1

As already mentioned the file use fix length of fields and records, we already have some knowledge of the data so lets try to find the length of record and hopefully also fields, to get that lets use following command:

hexdump -C dtv_channel.txt

Lets use colors to highlight few thinks
Beginning of record
Index, Channel Number, Length of channel name
Channel Name

AddressData in HEXHuman readable data
00004da000 00 00 00 00 00 00 00 17 00 0f 00 09 00 00 00|................|
00004db053 6c 61 67 72 20 54 56 00 00 00 00 00 00 00 00|Slagr TV........|
00004dc000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
00004dd010 02 86 10 00 fb 85 10 80 56 5f 2e 00 00 00 00|.........V_.....|
00004de008 00 00 00 cb 20 02 03 01 16 00 00 00 00 00 00|..... ..........|
00004df001 00 00 00 00 00 10 00 08 00 00 00 53 6c 61 67|............Slag|
00004e0072 20 54 56 00 00 00 00 00 00 00 00 00 00 00 00|r TV............|
00004e1000 00 00 00 00 00 00 00 00 00 00 00 01 09 01 00|................|
00004e2000 00 00 00 01 09 02 00 00 00 00 00 00 00 00 00|................|
00004e3000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
00004e8000 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00|................|
00004e9002 09 03 00 65 7a 63 00 00 00 00 00 00 00 00 00|....ezc.........|
00004ea000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
00004ed000 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
00004ee000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
000050b000 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
000050c000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
0000510000 00 00 00 00 00 00 00 18 00 10 00 07 00 00 00|................|
0000511041 43 54 49 56 45 00 00 00 00 00 00 00 00 00 00|ACTIVE..........|
0000512000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
0000513000 00 00 00 88 fe 85 10 80 56 5f 2e 00 00 00 00|.........V_.....|
0000514008 00 00 00 cb 20 02 03 01 1c 00 00 00 00 00 00|..... ..........|
0000515001 00 00 00 00 00 10 00 06 00 00 00 41 43 54 49|............ACTI|
0000516056 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00|VE..............|
0000517000 00 00 00 00 00 00 00 00 00 00 00 01 15 01 00|................|
0000518000 00 00 00 01 15 02 00 00 00 00 00 00 00 00 00|................|
0000519000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
000051e000 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00|................|
000051f002 15 03 00 65 7a 63 00 00 00 00 00 00 00 00 00|....ezc.........|
0000520000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
0000523000 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
0000524000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
0000541000 ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
0000542000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00|................|
*
0000546000 00 00 00 00 00 00 00 47 0e f9 12 |........G...|

by subtracting two addresses of record beginning
4da0 (19872 Dec)
5100 (20736 Dec)
we will get record length = 864
first 8 bytes can be droped

Now with this knowledge we can split into records, we can use split -b 864 and we will have one record per file. The we can use following to check more on structure of records:

for f in `ls x*`; do echo $f; hd $f; done

xat
00000000  00 00 00 00 00 00 00 00  13 00 0b 00 0b 00 00 00  |................|
00000010  50 72 69 6d 61 20 4c 4f  56 45 00 00 00 00 00 00  |Prima LOVE......|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  e0 b0 85 10 d0 a9 85 10  80 56 5f 2e 00 00 00 00  |.........V_.....|
00000040  08 00 00 00 cb 20 02 03  04 03 00 00 00 00 00 00  |..... ..........|
00000050  01 00 00 00 00 00 10 00  0a 00 00 00 50 72 69 6d  |............Prim|
00000060  61 20 4c 4f 56 45 00 00  00 00 00 00 00 00 00 00  |a LOVE..........|
00000070  00 00 00 00 00 00 00 00  00 00 00 00 01 02 01 00  |................|
00000080  00 00 00 00 01 02 02 00  00 00 00 00 00 00 00 00  |................|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000e0  00 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
000000f0  02 02 03 00 65 7a 63 00  00 00 00 00 00 00 00 00  |....ezc.........|
00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000130  00 ff 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000002b0  00 00 00 00 00 00 00 00  00 00 00 00 01 00 00 00  |................|
000002c0  00 00 00 00 00 00 00 00  03 02 01 01 00 00 00 00  |................|
000002d0  65 7a 63 00 00 00 00 00  00 00 00 00 00 00 00 00  |ezc.............|
000002e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000310  00 ff 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000320  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000360
xau
00000000  00 00 00 00 00 00 00 00  14 00 0c 00 0b 00 00 00  |................|
00000010  50 72 69 6d 61 20 5a 4f  4f 4d 00 00 00 00 00 00  |Prima ZOOM......|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000030  68 b4 85 10 58 ad 85 10  80 56 5f 2e 00 00 00 00  |h...X....V_.....|
00000040  08 00 00 00 cb 20 02 03  06 03 00 00 00 00 00 00  |..... ..........|
00000050  01 00 00 00 00 00 10 00  0a 00 00 00 50 72 69 6d  |............Prim|
00000060  61 20 5a 4f 4f 4d 00 00  00 00 00 00 00 00 00 00  |a ZOOM..........|
00000070  00 00 00 00 00 00 00 00  00 00 00 00 01 14 01 00  |................|
00000080  00 00 00 00 01 14 02 00  00 00 00 00 00 00 00 00  |................|
00000090  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000e0  00 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
000000f0  02 14 03 00 65 7a 63 00  00 00 00 00 00 00 00 00  |....ezc.........|
00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000130  00 ff 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000310  00 ff 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000320  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000360


We can see that from address 310 there are just null's, we also can see that in some cases there are data between address 90 and 310, however checking on context those data doesn't help us to recognize between radio and TV channel so we can actually do two more things to make more clear:

We can just print first 144 bytes and also we can drop first 8 bytes as we figure out previously and compare again, now it will be easier to find what's always same for Radio stations and TV Stations.

root@raspberrypi:/media/nas/public# for f in `ls x*`; do echo $f; hexdump -s 8 -n 144 -C $f; done
xaa
00000008  01 00 01 00 08 00 00 00  43 54 20 31 20 4a 4d 00  |........CT 1 JM.|
00000018  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000028  00 00 00 00 00 00 00 00  f8 c7 85 10 00 00 00 00  |................|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  01 01 00 00 00 00 00 00  01 00 00 00 00 00 10 00  |................|
00000058  07 00 00 00 43 54 20 31  20 4a 4d 00 00 00 00 00  |....CT 1 JM.....|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 01 01 01 00  00 00 00 00 01 01 02 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098
xab
00000008  05 00 01 00 10 00 00 00  43 52 6f 20 52 41 44 49  |........CRo RADI|
00000018  4f 5a 55 52 4e 41 4c 00  00 00 00 00 00 00 00 00  |OZURNAL.........|
00000028  00 00 00 00 00 00 00 00  60 8d 85 10 b8 83 85 10  |........`.......|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  01 41 00 00 00 00 00 00  02 00 00 00 00 00 20 00  |.A............ .|
00000058  0f 00 00 00 43 52 6f 20  52 41 44 49 4f 5a 55 52  |....CRo RADIOZUR|
00000068  4e 41 4c 00 00 00 00 00  00 00 00 00 00 00 00 00  |NAL.............|
00000078  00 00 00 00 11 10 00 00  00 00 00 00 00 00 00 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098
xac
00000008  02 00 02 00 05 00 00 00  43 54 20 32 00 00 00 00  |........CT 2....|
00000018  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000028  00 00 00 00 00 00 00 00  80 cb 85 10 f8 c7 85 10  |................|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  02 01 00 00 00 00 00 00  01 00 00 00 00 00 10 00  |................|
00000058  04 00 00 00 43 54 20 32  00 00 00 00 00 00 00 00  |....CT 2........|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 01 02 01 00  00 00 00 00 01 02 02 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098
xad
00000008  06 00 02 00 0b 00 00 00  43 52 6f 20 44 56 4f 4a  |........CRo DVOJ|
00000018  4b 41 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |KA..............|
00000028  00 00 00 00 00 00 00 00  70 d4 85 10 60 8d 85 10  |........p...`...|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  02 41 00 00 00 00 00 00  02 00 00 00 00 00 20 00  |.A............ .|
00000058  0a 00 00 00 43 52 6f 20  44 56 4f 4a 4b 41 00 00  |....CRo DVOJKA..|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 11 11 00 00  00 00 00 00 00 00 00 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098
xae
00000008  03 00 03 00 06 00 00 00  43 54 20 32 34 00 00 00  |........CT 24...|
00000018  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000028  00 00 00 00 00 00 00 00  08 cf 85 10 80 cb 85 10  |................|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  03 01 00 00 00 00 00 00  01 00 00 00 00 00 10 00  |................|
00000058  05 00 00 00 43 54 20 32  34 00 00 00 00 00 00 00  |....CT 24.......|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 01 03 01 00  00 00 00 00 01 03 02 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098
xaf
00000008  07 00 03 00 0b 00 00 00  43 52 6f 20 56 4c 54 41  |........CRo VLTA|
00000018  56 41 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |VA..............|
00000028  00 00 00 00 00 00 00 00  70 c4 85 10 70 d4 85 10  |........p...p...|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  03 41 00 00 00 00 00 00  02 00 00 00 00 00 20 00  |.A............ .|
00000058  0a 00 00 00 43 52 6f 20  56 4c 54 41 56 41 00 00  |....CRo VLTAVA..|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 11 12 00 00  00 00 00 00 00 00 00 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098
xag
00000008  04 00 04 00 09 00 00 00  43 54 20 73 70 6f 72 74  |........CT sport|
00000018  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000028  00 00 00 00 00 00 00 00  58 53 85 10 08 cf 85 10  |........XS......|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  04 01 00 00 00 00 00 00  01 00 00 00 00 00 10 00  |................|
00000058  08 00 00 00 43 54 20 73  70 6f 72 74 00 00 00 00  |....CT sport....|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 01 04 01 00  00 00 00 00 01 04 02 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098

So now I have everything I need I just need to have it in nice output:

Channel number
Channel name
Type of channel (Radio/TV)

00000008  01 00 01 00 08 00 00 00  43 54 20 31 20 4a 4d 00  |........CT 1 JM.|
00000018  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000028  00 00 00 00 00 00 00 00  f8 c7 85 10 00 00 00 00  |................|
00000038  80 3a 11 20 00 00 00 00  08 00 00 00 cb 20 12 01  |.:. ......... ..|
00000048  01 01 00 00 00 00 00 00  01 00 00 00 00 00 10 00  |................|
00000058  07 00 00 00 43 54 20 31  20 4a 4d 00 00 00 00 00  |....CT 1 JM.....|
00000068  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000078  00 00 00 00 01 01 01 00  00 00 00 00 01 01 02 00  |................|
00000088  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000098

#! /bin/sh

DTV_FILE='/media/nas/public/dtv_channel.txt'
split -b 864 $DTV_FILE

for f in `ls x*`
do
  channel_num_hd=`hexdump -s 10 -n 1 -e '"%_u"' $f`
  channel_num=`ascii -t $channel_num_hd | cut -d ' ' -f 4`
  channel_type=`hexdump -s 126 -n 1 -e '"%_u"' $f | sed 's/soh/TV/' | sed 's/nul/Radio/'`
  channel_name=`hexdump -s 16 -n 32 -v -e '"%_u\_"' $f | sed 's/nul_*//g' | sed 's/_//g'`
  echo "$channel_num,$channel_type,$channel_name"
done

rm -f x*


Thursday, September 18, 2014

UPnP and Python

I guess that you already know what UPnP is. Let's see how we can write some python code which we can use to control some UPnP device. First we need to discover device and services provided by it, for this we will use gssdp-discover -n 10 gssdp-discover is part of the gupnp-tools package.
gssdp-discover -n 10
We will see something like this:
resource available
  USN:      uuid:03166842-2743-2000-0000-7c1e52c26ca7::upnp:rootdevice
  Location: http://10.0.0.9:1027/
resource available
  USN:      uuid:03166842-2743-2000-0000-7c1e52c26ca7::urn:schemas-upnp-org:device:MediaRenderer:1
  Location: http://10.0.0.9:1027/
resource available
  USN:      uuid:03166842-2743-2000-0000-7c1e52c26ca7
  Location: http://10.0.0.9:1027/
resource available
  USN:      uuid:03166842-2743-2000-0000-7c1e52c26ca7::urn:schemas-upnp-org:service:AVTransport:1
  Location: http://10.0.0.9:1027/
resource available
  USN:      uuid:03166842-2743-2000-0000-7c1e52c26ca7::urn:schemas-upnp-org:service:ConnectionManager:1
  Location: http://10.0.0.9:1027/
resource available
  USN:      uuid:03166842-2743-2000-0000-7c1e52c26ca7::urn:schemas-upnp-org:service:RenderingControl:1
  Location: http://10.0.0.9:1027/
As you can see this device provides MediaRenderer, AVTransport, ConnectionManager and RenderingControl. This means we can play media on this device and control it (Play, Pause, Stop, Volume Up, ...) We know that UPnP is basically SOAP so we first need to create header,
POST control URL HTTP/1.1
HOST: host:port
CONTENT-LENGTH: bytes in body
CONTENT-TYPE: text/xml; charset="utf-8"
SOAPACTION: "urn:schemas-upnp-org:service:serviceType:v#actionName”
As you can see above we will need to find control URL, host:port (this we already know from gssdp-discovery) and action we want to perform. If we use any browser and open url in give by Location (from gssdp-discovery) we will get XML with basic information about device plus services provided. There is tag ServiceList which contains info about services for each we will need controlURL and SCPDURL, SCPDURL is path xml definition of function provided by the service. Bellow we can see example of service. So we can fin out that control URL we need is /AVTrasnport/control and definition of actions we will find in host:port/AVTransport/scpd.xml
<service>
  <serviceType>urn:schemas-upnp-org:service:AVTransport:1</serviceType>
  <serviceId>urn:upnp-org:serviceId:AVTransport_1F88B77A-8236-49b9-B344-974969412930</serviceId>
  <SCPDURL>AVTransport/scpd.xml</SCPDURL>
  <controlURL>AVTransport/control</controlURL>
  <eventSubURL>AVTransport/event</eventSubURL>
</service>
Now we will open http://host:port/AVTransport/scpd.xml and find action we want to perform, bellow we can see example of such action definitoin, we will need name and argument with direction in, direction out is actually what we will get in response.
<action>
  <name>GetMediaInfo</name>
   <argumentlist>
     <argument>
       <name>InstanceID</name>
       <direction>in</direction>
       <relatedstatevariable>A_ARG_TYPE_InstanceID</relatedstatevariable>
     </argument>
     <argument>
       <name>NrTracks</name>
       <direction>out</direction>
       <relatedstatevariable>NumberOfTracks</relatedstatevariable>
     </argument>
     <argument>
       <name>MediaDuration</name>
       <direction>out</direction>
       <relatedstatevariable>CurrentMediaDuration</relatedstatevariable>
     </argument>
     <argument>
       <name>CurrentURI</name>
       <direction>out</direction>
       <relatedstatevariable>AVTransportURI</relatedstatevariable>
     </argument>
     ...
  </argumentlist>
</action>
In our case action name is GetMediaInfo and argument is InstanceID, this instanceID as we can further see is related to variable A_ARG_TYPE_InstanceID if we search further in the definition xml we find this statevariable and its default value.
<statevariable sendevents="no">
  <name>A_ARG_TYPE_InstanceID</name>
  <datatype>ui4</datatype>
  <defaultvalue>0</defaultvalue>
</statevariable>
SOAP Message should look like this:
<s:Envelope xmlns: s=“http://schemas.xmlsoap.org/soap/envelope” s:encodingStyle=“http://schemas.xmlsoap.org/soap/encoding”>
<s:Body>
    <u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v">
        <argumentName>in arg value</argumentName>       
   </u:actionName>
</s:Body>
</s:Envelope>
As we already know all we need we will create testUPnP.py script in python which will take action as argument
import sys
import httplib, urllib
import re

action = sys.argv[1]

conn = httplib.HTTPConnection("10.0.0.9:1027")
soap_data = '<s:Envelope xmlns: s="http://schemas.xmlsoap.org/soap/envelope" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding"><s:Body><u:'+action+' xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:'+action+'></s:Body></s:Envelope>'

params = urllib.urlencode({'q': 'set'})
headers = { "Content-Type": "text/xml", "Content-Length": "%d" % len(soap_data), "SOAPACTION": "urn:schemas-upnp-org:service:AVTransport:1#"+action+'"' }

conn.request("POST", "/AVTransport/control", "", headers)
conn.send(soap_data)

response = conn.getresponse()

#FOR DEBUG
print response.status, response.reason
print response.read()

Wednesday, August 14, 2013

Yamaha Network Control

During my home automation project, where I want to use Raspberry Pi running lighttpd to make web for home automation, I've learned a bit about Yamaha network control and because it took me some time to find the info. I would like to share my findings.
There are two ways you might control this device:
  • UPnP, which doesn't seem to work properly as far any attempt to play music from computer failed.
  • YNC (Yamaha network control), unfortunatly I didn't find any official documentation about this protocol from Yamaha, however devices hold this documentation them self, it's basically extension of UPnP.

Bellow is part of UPnP specification showing controlURL and SCPDURL, SCPDURL is path xml definition of function provided by the service. (More on UPnP here)
<yamaha:X_device>
  <yamaha:X_serviceList>
    <yamaha:X_service>
      <yamaha:X_specType>urn:schemas-yamaha-com:service:X_YamahaRemoteControl:1</yamaha:X_specType>
      <yamaha:X_controlURL>/YamahaRemoteControl/ctrl</yamaha:X_controlURL>
      <yamaha:X_unitDescURL>/YamahaRemoteControl/desc.xml</yamaha:X_unitDescURL>
    </yamaha:X_service>
  </yamaha:X_serviceList>
</yamaha:X_device> 
I also find that somebody collect those and transform them into excel file which, might be more readble here
Here is backup in cause the original link doesn't work.
Based on the specification in picture we created the sample message to increase volume level

<YAMAHA_AV cmd="PUT">
  <Main_Zone>
    <Volume>
      <Lvl>
        <Val>Up 1 dB</Val>
        <Exp></Exp>
        <Unit></Unit>
      </Lvl>
    </Volume>
  </Main_Zone>
</YAMAHA_AV>
And here is piece of python code to send it.
#! /usr/bin/python

import httplib, urllib
import re

conn = httplib.HTTPConnection("10.0.0.36:80")
xml_data='<YAMAHA_AV cmd="PUT"><Main_Zone><Volume><Lvl><Val>Up 1 dB</Val><Exp></Exp><Unit></Unit></Lvl></Volume></Main_Zone></YAMAHA_AV>'

params = urllib.urlencode({'q': 'set'})
headers = { 'Content-Type': 'application/xml', "Content-Length": "%d" % len(xml_data)}

conn.request("POST", "/YamahaRemoteControl/ctrl", "", headers)
conn.send(xml_data)

response = conn.getresponse()

#FOR DEBUG
#print response.status, response.reason
#print response.read()

conn.close()
As far as YNC returns XML you can use CSS to display the information return on web, below is python code requesting information about media curently played. As well as CSS code to display it.

HTR-4065_PlayInfo.py
#! /usr/bin/python

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

conn = httplib.HTTPConnection("10.0.0.36:80")
xml_play_info = '<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="GET"><SERVER><Play_Info<GetParam</Play_Info></SERVER></YAMAHA_AV>'


params = urllib.urlencode({'q': 'set'})
headers = { 'Content-Type': 'application/xml', "Content-Length": "%d" % len(xml_play_info)}

conn.request("POST", "/YamahaRemoteControl/ctrl", "", headers)
conn.send(xml_play_info)

response = conn.getresponse()

#print response.status, response.reason
response_data = response.read()
print response_data

Here is the response
<YAMAHA_AV rsp="GET" RC="0">
  <SERVER>
    <Play_Info>
      <Feature_Availability>Ready</Feature_Availability>
      <Playback_Info>Play</Playback_Info>
      <Play_Mode>
        <Repeat>Off</Repeat>
        <Shuffle>Off</Shuffle>
      </Play_Mode>
      <Meta_Info>
        <Artist>Enya</Artist>
        <Album>Paint The Sky With Stars</Album>
        <Song>Boadicea</Song>
      </Meta_Info>
      <Album_ART>
        <URL>/YamahaRemoteControl/AlbumART/AlbumART.ymf</URL>
        <ID>243</ID>
        <Format>YMF</Format>
      </Album_ART>
    </Play_Info>
  </SERVER>
</YAMAHA_AV>
yncPlayInfo.css
Feature_Availability, Album_ART, Playback_Info {display: none}
Meta_Info, Play_Mode {display: block}
Meta_Info:before {content: "Currently Playing:"; font-weight: bold}
Play_Mode:before {content: "Play mode:"; font-weight: bold}
Artist, Album, Song {display: list-item; list-style-type: none}
Artist:before {content: "Artist: "; margin-left: 10px; font-weight: bold}
Album:before {content: "Album: "; margin-left: 10px; font-weight: bold}
Song:before {content: "Song: "; margin-left: 10px; font-weight: bold}
Repeat, Shuffle {display: list-item}
Repeat:before {content: "Repeat: "; margin-left: 10px; font-weight: bold}
Shuffle:before {content: "Shuffle: "; margin-left: 10px; font-weight: bold}

menu_status, menu_layer, attribute {display: none}
menu_name {font-weight: bold}
current_list {display: block}
txt {display: list-item; list-style-type: none; margin-left: 10px}

Wednesday, July 24, 2013

NEC MultiSync Ethernet Remote Control

Two years back I bought NEC MultiSync V321 one of the reasons was it have ethernet port and you can control it over the network.
The other reason is that there is documentation for it provided by NEC which can help you with commands, if you are intelligent and good enough to understand it. Which is probably not my case.
However NEC also offers NEC PD comms tool, which is application which let you control your NEC.
As I have Yamaha AV reciever (for which Yamaha provides control app) my intention recently was to have small app just to switch on/off the monitor and so limit number of remote controlers.
I also recently bought raspberry Pi and find good use for it. I'm running web server there and using cgi I can switch on/off my NEC and also Yamaha (will write about it in future as I will implement more features).
So what I did, I used NEC PD comms tool and wireshark to catch the tcp data payload for on and off, I wrote few lines in python to send those data and add few more to work nicely as cgi.

Here are the source codes:

NECOn.py
#! /usr/bin/python

import socket

monitor_ip = '10.0.0.35'
port = 7142
buffer_size = 1024
data_on = '\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x31\x03\x73\x0d'

new = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
new.connect((monitor_ip, port))
new.send(data_on)
recv_data = new.recv(buffer_size)
new.close()

print """
<html>
  <head>
    <meta http-equiv="refresh" content="0;url=http://10.0.0.37" />
    <title>You are going to be redirected</title>
  </head>
  <body>
    Redirecting...
  </body>
</html>
"""

NECOff.py
#! /usr/bin/python

import socket

monitor_ip = '10.0.0.35'
port = 7142
buffer_size = 1024
data_off = '\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x34\x03\x76\x0d'


mon_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mon_socket.connect((monitor_ip, port))
mon_socket.send(data_off)
recv_data = mon_socket.recv(buffer_size)
mon_socket.close()

print """
<html>
  <head>
    <meta http-equiv="refresh" content="0;url=http://10.0.0.37" />
    <title>You are going to be redirected</title>
  </head>
  <body>
    Redirecting...
  </body>
</html>
"""
For monitoring purpose I needed to find the howto check status of my NEC and recorded in the Database(I use sqlite3), even the response is just 25 bytes NEC dived it into 2 packets, so we are recording all packets and then check if the On or Off. NECStatus.py
#! /usr/bin/python

import sys
import socket
import sqlite3

monitor_ip = '10.0.0.35'
port = 7142
buffer_size = 2048
data_on = '\x01\x30\x41\x30\x41\x30\x36\x02\x30\x31\x44\x36\x03\x74\x0d'


new = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
new.connect((monitor_ip, port))
new.send(data_on)

data = ''

#message is split over several packets so need to get all content, message we expect have 25bytes
packet = new.recv(buffer_size)
data += packet
while len(data) < 25 or not packet:
   packet = new.recv(buffer_size)
   data += packet

new.close()

#Reponse OFF
#00AB120200D60000040004q
#Response ON
#00AB120200D60000040001t

off_response = b'\x30\x30\x41\x42\x31\x32\x30\x32\x30\x30\x44\x36\x30\x30\x30\x30\x30\x34\x30\x30\x30\x34'
on_response = bytes("\x30\x30\x41\x42\x31\x32\x30\x32\x30\x30\x44\x36\x30\x30\x30\x30\x30\x34\x30\x30\x30\x31")


#there seems to be some not printable chars because of packet fragmentation
#using index is dirty hack but don't care
if data[23] == off_response[21]:
  power_status = "Off"
elif data[23] == on_response[21]:
  power_status = "On"
else:
  power_status = "Unknown"

#Now we need to update sqlite with status

select_query = "SELECT cur_state,polls_in_state FROM dev_status WHERE mac = '00:25:5c:2e:36:39';"
#print update_query
new_polls=1

judodb = sqlite3.connect('/var/www/judo.db')
cur = judodb.cursor()
rows = cur.execute(select_query)
for row in rows:
  prev_state = row[0]
  prev_polls = row[1]
if prev_state == power_status:
  new_polls = prev_polls + 1
print prev_state + "\t\t" + str(new_polls)
update_query = "UPDATE dev_status SET cur_state = \'" + power_status + "\', polls_in_state = " + str(new_polls)  + " WHERE mac = '00:25:5c:2e:36:39'"
cur.execute(update_query)
judodb.commit()
judodb.close()

If you have any questions you can always contact me.

Sunday, August 19, 2012

Colaborativ shopping

Situation:

I've had a small problem, when we (me and my girlfriend) was planning for shopping. It was bit chaotic.... she usually during evening or when she have break in work was browsing and creating shopping list.
However it was me who was the list "holder" I have the list on my android phone. In last week she also starts to taking my table in the evening and browsing on it. Even she don't like the f*cking touch thing she use it rather then her laptop. But she doesn't like to copy past in android. Me neither by the way.

Problem:

OK, so problem is how to automatically create the list which I can manage, somebody else can add items there and we don't need nothing extra then email, cause on the android you can share the page and on laptop it's not so much different.

Solution:

I combined 3 things together where gmail, ifttt and evernote.
1) In gmail I've created new label "Nakup" (something like "shoping list" in czech), and create a rule that all mails from me(in case I'll share something from my android) and my girlfriend with subject containing "N(n)akup" goes to this label.
2)I've created rule in ifttt every new Nakup label mail in my gmail is taken and base on the subject in evernote create new list and content of mail is added in it or if exist then added to existing.


How it works:

Let's say my girlfriend finds something in Ikea she wants, she just "share page" from my andriod and send mail to myself with subject "Nakup - Ikea".
New shopping list "Nakup - Ikea" is created with content of that mail.
Later on when she finds something else she send's me another mail (from her mail) with same subject Nakup - Ikea and contaent of this mail is added to same list.

I can edit the list in evernote any time I want.

This is best solution with general (Not specialized) tools I've come with till now.
If you are suing something better, please let me know.

Wednesday, November 9, 2011

net-snmp on fun_plug

I have ZyXEL NSA 320 at home so I wanted to use it's full capability, first step was to get "linux" there, first and for the moment last choice was FFP (Funz Fun Plug).
As far as I'm working in network monitoring other interest of mine was if I can have SNMP agent running there and yes I could, here is short guide how to install it. It's nothing hard.

1) Download and install net-snmp for ffp
wget http://inreto.de/dns323/fun-plug/0.5/extra-packages/All/net-snmp-5.5-1.tgz
funpkg -i net-snmp-5.5-1.tgz
2) Configure net-snmp, best way to do so is use snmpconf program, which is menu based commandline interface which helps you to setup snmp deamon. More info can be find here http://net-snmp.sourceforge.net/tutorial/tutorial-5/demon/snmpd.html

3) Start snmp deamon during start of system
#!/ffp/bin/sh
# PROVIDE: snmpd
. /ffp/etc/ffp.subr
name="snmpd"
command="/ffp/sbin/snmpd"
telnetd_flags="-l /ffp/bin/sh"
run_rc_command "$1"
4) Start snmpd deamon and check if it works. See example bellow, don't forget to change IP and community to correspond to your own settings.

C:\Users\j.kindl>snmpwalk -v 2c -c gnet-ro 10.0.0.33 system
SNMPv2-MIB::sysDescr.0 = STRING: Linux nsa320 2.6.31.8 #1 Wed May 18 20:18:38 CS
T 2011 armv5tel
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::org
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (14061) 0:02:20.61
SNMPv2-MIB::sysContact.0 = STRING: plord@
SNMPv2-MIB::sysName.0 = STRING: nsa320
SNMPv2-MIB::sysLocation.0 = STRING: Unknown
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (3) 0:00:00.03
SNMPv2-MIB::sysORID.1 = OID: SNMP-MPD-MIB::snmpMPDMIBObjects.3.1.1
SNMPv2-MIB::sysORID.2 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORID.3 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
SNMPv2-MIB::sysORID.4 = OID: SNMPv2-MIB::snmpMIB
SNMPv2-MIB::sysORID.5 = OID: TCP-MIB::tcpMIB
SNMPv2-MIB::sysORID.6 = OID: IP-MIB::ip
SNMPv2-MIB::sysORID.7 = OID: UDP-MIB::udpMIB
SNMPv2-MIB::sysORID.8 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup
SNMPv2-MIB::sysORDescr.1 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.2 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.3 = STRING: The SNMP Management Architecture MIB.
SNMPv2-MIB::sysORDescr.4 = STRING: The MIB module for SNMPv2 entities
SNMPv2-MIB::sysORDescr.5 = STRING: The MIB module for managing TCP implementations
SNMPv2-MIB::sysORDescr.6 = STRING: The MIB module for managing IP and ICMP implementations
SNMPv2-MIB::sysORDescr.7 = STRING: The MIB module for managing UDP implementations
SNMPv2-MIB::sysORDescr.8 = STRING: View-based Access Control Model for SNMP.
SNMPv2-MIB::sysORUpTime.1 = Timeticks: (2) 0:00:00.02
SNMPv2-MIB::sysORUpTime.2 = Timeticks: (2) 0:00:00.02
SNMPv2-MIB::sysORUpTime.3 = Timeticks: (2) 0:00:00.02
SNMPv2-MIB::sysORUpTime.4 = Timeticks: (2) 0:00:00.02
SNMPv2-MIB::sysORUpTime.5 = Timeticks: (3) 0:00:00.03
SNMPv2-MIB::sysORUpTime.6 = Timeticks: (3) 0:00:00.03
SNMPv2-MIB::sysORUpTime.7 = Timeticks: (3) 0:00:00.03
SNMPv2-MIB::sysORUpTime.8 = Timeticks: (3) 0:00:00.03