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

Monday, December 15, 2008

Technical emails my best practice

When I was today preparing the presentation about UNIX basic I decide to put some UNIX philosophy slides on the beginning of it. Because I've read Raymond's Art of Unix Programing sometime ago I tought it would be perfect to use the some rules from him. So I go to the internet and find the list of rules from this great book. When I was reading them and figuring out which will be understandable for audience I said wait a moment some of those rules could be applied also in people relationships and mostly in written communication. 

The problem of today is that we are cooperating world wide in most of the companies nowadays and we use english to understand each others, well but not everybody is same level and after you send email, which is clear and perfectly understandable for you can make recipient angry, because of misunderstanding. Then you deal the call and say: "ohh sorry, it actually is about something else and it was not supposed to be offensive." In better case you just spend several more minutes to explain what was in email. But honestly it's waisting of time, because you could write your mail better.
Most of those problems of misunderstanding and explaining later on are cause by technician speaking to non-technician, in technical language and put things in complicated sentence. So we have here combination of different level of knowledge as well as different level of language skill. So here bellow find some Unix design rules which could be applied for mail communication:  

Rule of Modularity: Write simple parts connected by clean interfaces. 
Write simple statements, which are not to be misinterpreted and are connected in easy logical way. Rather use more simple sentences then one long.  

Rule of Clarity: Clarity is better than cleverness. 
Don't try to show your self as clever guy, because what is evident for you is not evident for others and they are not so much involved in topic as you. Expect your partner doesn't know the technical part so explain him like you would explain this to children.  

Rule of Transparency: Design for visibility to make inspection and debugging easier. 
If you are explaining some technical problem in the mail if you use simple statements instead of long sentences it's also more readable for other technicians. They can more easily follow the problem, because they doesn't need to search fact's hidden in the lot of nice 'colorfull' text.  

Rule of Robustness: Robustness is the child of transparency and simplicity.
If you will follow rules above you will have longer mail probably, but on the end more understandable and simple.

Rule of Repair: When you must fail, fail noisily and as soon as possible. 
This is not so much about communication, but more about behavior and it's not relevant to programming only but to any problem you may face. If you speak noisily about the problem and what can happened if it will not be solved people will listen more and it will be definitely easier to solve small problem and prevent bigger. In worst case you can then say: "Hey I've told you it's gonna be problem." So you at least are covered.  

Rule of Diversity: Distrust all claims for "one true way". 
Stay open to new ideas, even non-technical people could provide good technical solution or at least give you a hint or provide very good idea.

I've put link to this post to linkedin and ask the people there to put there tips about this topic. Here are the most interesting respons I've got:

I try and use pictures and non technical terms to explain technical problems to non technical people .The simple the better. Alot of people have a short attention span especially with the over abundance of information out there and if they don't understand what your explaining chances are they will lose interest.  


In addition to screen-shots, I find that a numbered list of steps works wonders. If they run into difficulty, any follow-up communication can refer specifically to a step number. Just make sure that you keep each step simple and try it out yourself before sending.  


It is a hard thing to do, but my best advice is to try to put yourself in the shoes of the person to whom you are writing. Try to imagine what it would be like to read the email if you knew nothing about it. Or imagine that the recipient is a 12-year old.  
And, keep the technical jargon, abbreviations, and acronyms out altogether.  


In tech support, I found it best to send screenshots or flash videos to explain a topic and train the customer on what needs to be done. 
A great free tool is Jing. Available at http://jingproject.com/  

Tuesday, November 4, 2008

CiscoSecure ACS Password recovery


Long time ago I was trying to search how to get in to Cisco ACS when I forgot my password.
When I searched on google I didn't find anything usefull, after all I find the way my self and to my suprise it's nothing secret or hard to find you just need to know what to search to be able to find it.
But because "CiscoSecure ACS Password recovery" is not working here is howto and from now on it maybe possible to find it ;-)
By default it's possible to access the CiscoSecure ACS admin page without login from localhost, but sometimes this is changed and even when accessing from localhost you need to use login and password. There is ofcourse way how to put default behavior back.
You need to have rights to change the registry if you have then do folloving
1)Open regedit
2) Go to [HKEY_LOCAL_MACHINE\SOFTWARE\Cisco\CiscoAAAv3.3\CSAdmin\Security]
3) Change "allowAutoLocalLogin" to 0
Now you will be able to access ACS admin page from localhost without login.
P.S.: Even you can find this HOWTO on more side I was not able to find it asking google for "ACS Password recovery" I hope everybody will be possible to do so.