In [1]:
#Socket client example in python
import socket #for sockets
import sys #for exit
import struct
from __future__ import division
import time
import sys,io
import string
import asynchat
In [2]:
def dprint(m):
for c in m:
if ord(c)==0x3b :
print
print "0x%02x" %ord(c),
print
def checksum(msg):
return ((~sum([ord(c) for c in msg]) + 1) ) & 0xFF
In [3]:
class scope(asynchat.async_chat):
def __init__(self, addr='1.2.3.4', port=2000):
asynchat.async_chat.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect((addr, port))
self.ibuffer = []
self.obuffer = ''
self.reading_headers = True
self.handling = False
self.set_terminator('*HELLO*')
self.startup=True
# grab some more data from the socket,
# throw it to the collector method,
# check for the terminator,
# if found, transition to the next state.
def handle_read (self):
try:
data = self.recv (self.ac_in_buffer_size)
except socket.error, why:
if why.args[0] in _BLOCKING_IO_ERRORS:
return
self.handle_error()
return
self.ac_in_buffer = self.ac_in_buffer + data
# Continue to search for self.terminator in self.ac_in_buffer,
# while calling self.collect_incoming_data. The while loop
# is necessary because we might read several data+terminator
# combos with a single recv(4096).
while self.ac_in_buffer:
lb = len(self.ac_in_buffer)
terminator = self.get_terminator()
if not terminator:
# no terminator, collect it all
self.collect_incoming_data (self.ac_in_buffer)
self.ac_in_buffer = ''
elif isinstance(terminator, int) or isinstance(terminator, long):
# numeric terminator
n = terminator
if lb < n:
self.collect_incoming_data (self.ac_in_buffer)
self.ac_in_buffer = ''
self.terminator = self.terminator - lb
else:
self.collect_incoming_data (self.ac_in_buffer[:n])
self.ac_in_buffer = self.ac_in_buffer[n:]
self.terminator = 0
self.found_terminator()
else:
# 3 cases:
# 1) end of buffer matches terminator exactly:
# collect data, transition
# 2) end of buffer matches some prefix:
# collect data to the prefix
# 3) end of buffer does not match any prefix:
# collect data
terminator_len = len(terminator)
index = self.ac_in_buffer.find(terminator)
if index != -1:
# we found the terminator
if index > 0:
# don't bother reporting the empty string (source of subtle bugs)
# Sometimes one needs empty strings!
pass
#print 'Term found'
sys.stdout.flush()
self.collect_incoming_data (self.ac_in_buffer[:index])
self.ac_in_buffer = self.ac_in_buffer[index+terminator_len:]
# This does the Right Thing if the terminator is changed here.
self.found_terminator()
else:
# check for a prefix of the terminator
index = asynchat.find_prefix_at_end (self.ac_in_buffer, terminator)
if index:
if index != lb:
# we found a prefix, collect up to the prefix
self.collect_incoming_data (self.ac_in_buffer[:-index])
self.ac_in_buffer = self.ac_in_buffer[-index:]
break
else:
# no prefix, collect it all
self.collect_incoming_data (self.ac_in_buffer)
self.ac_in_buffer = ''
def collect_incoming_data(self, data):
'''Buffer the data'''
#print 'Collect:',
#dprint(data)
sys.stdout.flush()
self.ibuffer.append(data)
def found_terminator(self):
if self.startup :
self.set_terminator('\x3b')
self.startup=False
self.ibuffer=[]
print 'Hello!'
sys.stdout.flush()
return
if self.reading_headers :
print 'msg:',
self.reading_headers=False
self.ibuffer=[]
self.set_terminator(1)
elif self.handling :
self.handling=False
self.reading_headers=True
self.set_terminator('\x3b')
#print self.ibuffer
self.msg=''.join(self.ibuffer)
dprint(self.msg)
if checksum(self.msg[:-1])!=ord(self.msg[-1]) :
print 'Checksum error!'
else :
self.handling=True
self.msglen=ord(self.ibuffer[0][0])
print '(%2d)' % self.msglen,
self.set_terminator(self.msglen+1)
sys.stdout.flush()
In [7]:
nse=scope('10.24.48.10')
asynchat.asyncore.loop(count=25)
nse.socket.close()
In [8]:
nse.socket.close()
In [119]:
?? asynchat.async_chat
In [10]:
targets={'ANY':'\x00',
'MB' :'\x01',
'HC' :'\x04',
'HC+':'\x0d',
'AZM':'\x10',
'ALT':'\x11',
'APP':'\x20',
'GPS':'\xb0',
'WiFi':'\xb5',
'BAT':'\xb6',
'CHG':'\xb7',
'LIGHT':'\xbf'
}
commands={
'MC_GET_POSITION':'\x01',
'MC_GOTO_FAST':'\x02',
'MC_SET_POSITION':'\x04',
'MC_SET_POS_GUIDERATE':'\x06',
'MC_SET_NEG_GUIDERATE':'\x07',
'MC_LEVEL_START':'\x0b',
'MC_GOTO_SLOW':'\x17',
'MC_SEEK_INDEX':'\x19',
'MC_SET_AUTOGUIDE_RATE':'\x46',
'MC_GET_AUTOGUIDE_RATE':'\x47',
'GET_VER':'\xfe',
'GET_BATT_STATUS':'\x10',
}
trgid={}
for k in targets.keys():
trgid[ord(targets[k])]=k
cmdid={}
for k in commands.keys():
cmdid[ord(commands[k])]=k
def checksum(msg):
return ((~sum([ord(c) for c in msg]) + 1) ) & 0xFF
def f2dms(f):
d=360*f
dd=int(d)
mm=int((d-dd)*60)
ss=(d-dd-mm/60)*3600
return dd,mm,ss
def parse_pos(dat,s=None,d=None):
if len(dat)==3 :
pos=struct.unpack('!i','\x00'+dat)[0]/2**24
return u'%03d°%02d\'%04.1f"' % f2dms(pos)
else :
return ''
def parse_bat(dat):
#dprint(dat)
batstat={
'\x00':'LOW',
'\x01':'MEDIUM',
'\x02':'HIGH',
}
if len(dat)==6 :
return u'%6s: %.4fV %s ' % ( batstat[dat[1]],
struct.unpack('!i',dat[2:])[0]/1e6,
'Charging' if dat[0]=='\x01' else 'Discharging' )
else :
return ''
def parse_10(dat,s=None,d=None):
if s==0xb6 or d==0xb6 :
return parse_bat(dat)
else :
return ''.join(['0x%02x ' % ord(b) for b in dat])
parsers={
'\x01':parse_pos,
'\x02':parse_pos,
'\x04':parse_pos,
'\x06':parse_pos,
'\x07':parse_pos,
'\x17':parse_pos,
'\x10':parse_10,
'\x11':parse_10,
}
def send_cmd(sck, src='APP', trg='AZM', cmd='GET_VER', data=''):
pre='\x3b'
msg=targets[src]+targets[trg]+commands[cmd]+data
msg=chr(len(msg))+msg
sck.sendall(pre+msg+chr(checksum(msg)))
def split_msgs(r,debug=False):
l=r.find('\x3b')+1
p=l
ml=[]
while p>-1:
p=r.find('\x3b',l)
#if debug : print l, p
ml.append(r[l:p]+r[p])
l=p+1
if debug : print ml
return ml
def parse_msg(m, debug=False):
'''
Parse bytes byond 0x3b.
Do not pass the message with preamble!
'''
l=ord(m[0])+1
msg=m[:l]
if debug :
print 'Parse:',
dprint(msg)
if chr(checksum(msg)) != m[l] :
print 'Checksum error: %x vs. %02x' % (checksum(msg) , ord(m[l]))
dprint(m)
l,src,dst,mid=struct.unpack('4B',msg[:4])
dat=msg[4:l+1]
#print 'len:', l
return l, src, dst, mid, dat
def print_msg(l,s,d,i,dat):
try :
print '[%d] %4s => %4s (%12s): ' % (l,trgid[s],trgid[d],cmdid[i]),
except KeyError :
print '[%d] %02x => %02x (%02x): ' % (l,s,d,i),
if chr(i) in parsers:
print parsers[chr(i)](dat,s,d),
else :
dprint(dat)
def rcv_msg(sck, trg='NET', debug=False):
r = sck.recv(4096)
#dprint(r)
we=ord(targets[trg])
ml=[]
for m in split_msgs(r,debug=debug):
if debug :
print 'RCV:',
dprint(m)
try :
l,s,d,i,dat=parse_msg(m,debug=debug)
if trg!='ANY' and d!=we and s!=we:
#print 'Not for us (%02x): %02x -> %02x' % (we, s, d)
continue
if debug : print_msg(l,s,d,i,dat)
ml.append([l,s,d,i,dat])
except IndexError :
print 'Parse ERROR:',
dprint(m)
return ml
def get_pos(sck,trg='ALT'):
send_cmd(s,trg=trg,cmd='MC_GET_POSITION')
time.sleep(0.05)
ml=rcv_msg(s)
dat='\x00'+ml[-1][-1]
return struct.unpack('!i',dat)[0]/2**24
def get_ver(sck,trg='MB'):
send_cmd(sck,trg=trg,cmd='GET_VER')
msg=rcv_msg(sck)[-1]
return tuple(['%02x' % ord(c) for c in msg[-1]])
def show_pos(sck):
azm=get_pos(sck,trg='AZM')
print u'\rAZM %03d°%02d\'%04.1f"' % f2dms(azm),
time.sleep(0.1)
alt=get_pos(sck,trg='ALT')
print u'ALT %+02d°%02d\'%04.1f"' % f2dms(alt),
In [53]:
#create an INET, STREAMing socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print 'Failed to create socket'
sys.exit()
print 'Socket Created'
host = '10.24.48.10';
port = 2000;
try:
remote_ip = socket.gethostbyname( host )
except socket.gaierror:
#could not resolve
print 'Hostname could not be resolved. Exiting'
sys.exit()
#Connect to remote server
s.connect((host , port))
print 'Socket Connected to ' + host + ' on ip ' + remote_ip
In [54]:
send_cmd(s,trg='AZM',cmd='MC_GET_POSITION')
for m in rcv_msg(s,'ANY'):
print_msg(*m)
for b in m[-1] : print ('%02x' % ord(b)),
print
send_cmd(s,trg='ALT',cmd='MC_GET_POSITION')
for m in rcv_msg(s,'ANY'):
print_msg(*m)
for b in m[-1] :print ('%02x' % ord(b)),
print
In [55]:
s.close()
In [ ]:
while True :
for m in rcv_msg(s,'ANY'):
print_msg(*m)
print
sys.stdout.flush()
time.sleep(0.05)
In [45]:
struct.unpack('!i','\x00\x00\x0b\xb8')[0]
Out[45]:
In [69]:
send_cmd(s,src='APP',trg='AZM',cmd='GET_VER')
print rcv_msg(s,trg='APP')
time.sleep(0.1)
send_cmd(s,src='APP',trg='ALT',cmd='GET_VER')
print rcv_msg(s,trg='APP')
In [64]:
send_cmd(s,src='APP',trg='AZM',cmd='MC_GET_AUTOGUIDE_RATE')
time.sleep(0.1)
for m in rcv_msg(s,'APP'):
print_msg(*m)
print
time.sleep(0.1)
send_cmd(s,src='APP',trg='AZM',cmd='MC_SET_AUTOGUIDE_RATE',data='\x80')
time.sleep(0.1)
for m in rcv_msg(s,'APP'):
print_msg(*m)
print
time.sleep(0.1)
send_cmd(s,src='APP',trg='AZM',cmd='MC_GET_AUTOGUIDE_RATE')
time.sleep(0.1)
for m in rcv_msg(s,'APP'):
print_msg(*m)
print
In [24]:
send_cmd(s,src='NET',trg='HC+',cmd='GET_VER')
rcv_msg(s,trg='ANY')
Out[24]:
In [277]:
send_cmd(s,trg='AZM',cmd='MC_GET_POSITION')
rcv_msg(s)
send_cmd(s,trg='ALT',cmd='MC_GET_POSITION')
rcv_msg(s)
Out[277]:
In [287]:
print get_ver(s,'HC')
In [279]:
send_cmd(s,trg='HC+',cmd='MC_GET_POSITION')
rcv_msg(s)
Out[279]:
In [289]:
print get_ver(s,'MB'), get_ver(s,'HC'), get_ver(s,'ALT'), get_ver(s,'AZM')
In [281]:
show_pos(s)
sys.stdout.flush()
In [284]:
for i in range(10):
show_pos(s)
sys.stdout.flush()
time.sleep(1)
In [173]:
def goto(s,alt,azm,spd='FAST'):
al=int(alt*2**24)
az=int(azm*2**24)
cmd='MC_GOTO_'+spd
send_cmd(s,trg='ALT',cmd=cmd,data=struct.pack('!i',al)[1:])
time.sleep(0.1)
send_cmd(s,trg='AZM',cmd=cmd,data=struct.pack('!i',az)[1:])
In [241]:
goto(s,0.0,0.0,spd='FAST')
In [199]:
def frac_to_fp24(x):
return struct.pack('!i',int(abs(x)*2**24))[1:]
def set_guiderate(s,altgr,azmgr):
ald='POS' if (altgr > 0) else 'NEG'
azd='POS' if (azmgr > 0) else 'NEG'
send_cmd(s,trg='ALT',cmd='MC_SET_'+ald+'_GUIDERATE',data=frac_to_fp24(altgr))
time.sleep(0.05)
send_cmd(s,trg='AZM',cmd='MC_SET_'+azd+'_GUIDERATE',data=frac_to_fp24(azmgr))
time.sleep(0.05)
In [233]:
set_guiderate(s,0,0)
In [240]:
send_cmd(s,trg='ALT',cmd='MC_LEVEL_START')
rcv_msg(s,debug=True)
Out[240]:
In [104]:
struct.unpack('!i','\x00\x02\x7d\xc6')[0]/2**24
Out[104]:
In [96]:
print((3+30/60+12/3600)/360)
for c in struct.pack('f',(3+30/60+12/3600)/360):
print('%02x' % ord(c))
print()
In [87]:
''.split()
Out[87]:
In [103]:
a='\x3b1aaaa\x3b2bbbbb\x3b3ccccc'
In [105]:
a.split('\x3b')[1:]
Out[105]:
In [ ]:
a.rfind()
In [143]:
split_msgs(a)
Out[143]:
In [142]:
a
Out[142]:
In [126]:
for c in a:
print '%02x' % ord(c) ,
In [ ]: