#!/usr/bin/env python # coding=utf-8 # # Python implementation of pd100_get.pl # # Author: Patrick Salecker # URL: http://www.salecker.org/software/pd100/en # Last modified: 06.12.2009 import time import os import socket import re import threading from struct import unpack import binascii HOST = "192.168.1.102" PORT = 80 PASSWORD = "" FILENAME = "test.jpg" INTERVAL = 0.1 ############################################################# # IF $typacket == 0x4f # dopacket: # -> - to camera # <- - from camera ############################################################# #t/f hex explanation # -> 00 - reset camera's config for logged user # <- 01 - show camera's mac address # -> 02 - login info sending to camera # <- 03 - login answer from camera (access/deny) # -> 10 - clearing something ???? # <- 16 - answer to "10", maybe cleared ???? # -> 04 - something setup asking ???? # <- 11 - some code sended (answer) # <- 05 - again something sended ############################################################## #$typacket == 0x56 ############################################################## # -> 00 - send code gotted from 05 in 0x04f setup (see upper) ############################################################## #$typacket == 0x4f ############################################################## # -> 07 - clearing something (or say "start") ############################################################## #$typacket == 0x56 ############################################################## # <- 01 - sending data ############################################################## def value2hexstring(value,length): #print hexstring(23,2),"17" #print hexstring(0,2),"00" #print hexstring(1,2),"01" #print hexstring(1,8),"01000000" hstr="%X" %value if len(hstr)==length: return hstr else: rest=length-len(hstr) if rest%2!=0: rest=rest-1 hstr="0"+hstr return hstr+"0"*(rest) def new_socket(): """connect to HOST,PORT """ s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST,PORT)) return s def makepacket(data,typacket,dopacket): dsize=len(data)/2 bla="4d4f5f%s%s00000000000000000000%s%s%s" % ( typacket, value2hexstring(dopacket,2), value2hexstring(dsize,8), value2hexstring(dsize,8), data ) #print bla if len(bla)%2!=0: bla=bla+"0" #print len(data)/2+46,len(bla) return binascii.unhexlify(bla) def countpacketdata(obj,buf): #perl #if ($buf =~ m/^\x4d\x4f\x5f(.)(.)\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(.{4})(.{4}).*/){ bla=re.compile(r"^\x4d\x4f\x5f(.)(.)\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(.{4})(.{4}).*") result= bla.split(buf) if len(result)>4: #print repr(result) obj.typacket = "%X"%ord(result[1]) obj.dopacket = ord(result[2]) psize= unpack("i",result[3])[0] psizecheck= unpack("i",result[4])[0] if psize == psizecheck: return psize else: return 0 else: return 0; class PD100: def __init__(self,filename=None): self.typacket="4f" self.dopacket=0 self.child=None #open a socket to HOST,PORT self.s=new_socket() buf=makepacket("",self.typacket,self.dopacket) self.s.send(buf) buf=self.receive_next() if (self.dopacket==1): mac=buf[2:14] print "Connected to MAC: %s" %mac else: print "Connected, but don't know MAC!" self.login() #login to camera self.dopacket=16 buf=makepacket("",self.typacket,self.dopacket) self.s.send(buf) buf=self.receive_next() if self.dopacket==22 and buf=="\x00": print "Answer to \"0x10\" OK!" else: if self.dopacket==22: print "Answer to \"0x10\" NOT OK!" else: print "No answer to \"0x10\"!" self.dopacket=4 buf=makepacket("02",self.typacket,self.dopacket) self.s.send(buf) #skip useless/unknown data self.receive_next() buf=self.receive_next() if self.dopacket==17: print "Answer to \"0x04\" give: %s" %repr(buf) buf=self.receive_next() if self.dopacket==5: client_hash=self.get_client_hash(buf) #create another socket in another thread for receiving images self.child=ChildThread(client_hash,filename) self.child.start() # say to control socket "start"! self.typacket="4f" self.dopacket=7 buf=makepacket("00000000",self.typacket,self.dopacket) self.s.send(buf) #self.loop() def login(self): """login to camera with "admin" and PASSWORD """ self.dopacket=2 pw=PASSWORD.encode("hex") + "0"*(26-(len(PASSWORD)*2)) buf=makepacket("61646D696E0000000000000000"+pw,self.typacket,self.dopacket) self.s.send(buf) buf=self.receive_next() if buf=="\x00\x00\x02" and self.dopacket==3: print "login OK!" else: print "ERROR: wrong login or packet cmd" def get_client_hash(self,buf): client_hash="" #print repr(buf),len(buf) for bla in buf: hexstr="%X"%ord(bla) #print len(hexstr) if len(hexstr)%2!=0: hexstr="0"+hexstr client_hash=client_hash+hexstr client_hash=client_hash.lower()[4:] print "Client Hash: %s (%s)" %(client_hash,len(client_hash)) return client_hash def loop(self): """wait for keep-alive packets and answer """ while True: try: buf=self.s.recv(23) except: self.stop() break countpacketdata(self,buf) if self.dopacket==255: # ~ every 60sec print "Send keep-alive!"; buf=makepacket("",self.typacket,self.dopacket) self.s.send(buf) elif self.dopacket==18: print "error: dopacket 18, break" break else: print "unknown data received: %s - %s" %(self.dopacket,repr(buf)) def stop(self): """clean disconnect """ # say to control socket "stop"! self.typacket="4f" self.dopacket=6 buf=makepacket("",self.typacket,self.dopacket) self.s.send(buf) self.s.close() self.child.stop() def receive_next(self): """receive the next packet """ buf=self.s.recv(23) dsize=countpacketdata(self,buf) buf=self.s.recv(dsize) return buf class MainThread(threading.Thread): def __init__ (self): threading.Thread.__init__(self) self.is_running=False self.cam=None def stop(self): self.is_running=False self.cam.stop() def run(self): print "Main run" self.is_running=True self.cam=PD100() self.cam.loop() def get_jpeg(self): return self.cam.child.jpeg def is_ready(self): if self.cam!=None and self.cam.child!=None: return True return False class ChildThread(threading.Thread): def __init__ (self,client_hash,filename=None): print "Child init, hash: %s" %client_hash self.client_hash=client_hash threading.Thread.__init__(self) self.typacket="56" self.dopacket=0 self.jpeg="" self.filename=filename self.is_running=False self.s=new_socket() def stop(self): print "Child stop" self.is_running=False time.sleep(INTERVAL) self.s.close() def run(self): print "Child run" self.is_running=True buf=makepacket(self.client_hash,self.typacket,self.dopacket) self.s.send(buf) # loop for image gets print "Child loop" while self.typacket=="56" and self.is_running is True: if self.receive_image(): #sleep if we received an image time.sleep(INTERVAL) def receive_image(self): """request and receive the next image """ buf=self.s.recv(23) dsize=countpacketdata(self,buf) if dsize>0: #print "image!",dsize buf=self.s.recv(dsize) while len(buf)