Created
March 18, 2014 15:28
-
-
Save qhwa/9622337 to your computer and use it in GitHub Desktop.
ruby script that grab pictures from LinkSprite TTL JPEG camera
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require 'serialport' | |
| require 'colored' | |
| require 'ruby-progressbar' | |
| class Y201Grab | |
| def self.a2s(*arr) | |
| arr.pack 'c*' | |
| end | |
| LK_RESET = a2s(0x56, 0x00, 0x26, 0x00) | |
| LK_RESET_RE = a2s(0x76, 0x00, 0x26, 0x00, 0x00) | |
| LK_PICTURE = a2s(0x56, 0x00, 0x36, 0x01, 0x00) | |
| LK_PICTURE_RE = a2s(0x76, 0x00, 0x36, 0x00, 0x00) | |
| LK_JPEGSIZE = a2s(0x56, 0x00, 0x34, 0x01, 0x00) | |
| LK_JPEGSIZE_RE = a2s(0x76, 0x00, 0x34, 0x00, 0x04, 0x00, 0x00) # then XH XL | |
| LK_STOP = a2s(0x56, 0x00, 0x36, 0x01, 0x03) | |
| LK_STOP_RE = a2s(0x76, 0x00, 0x36, 0x00, 0x00) | |
| LK_READPICTURE = a2s(0x56, 0x00, 0x32, 0x0C, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) #then KH KL | |
| LK_PICTURE_TIME = a2s(0x00, 0x0A) # .1 ms | |
| LK_READPICTURE_RE = a2s(0x76, 0x00, 0x32, 0x00, 0x00) | |
| JPEG_START = a2s(0xFF, 0xD8) | |
| JPEG_END = a2s(0xFF, 0xD9) | |
| LK_PIC_SIZE_640 = a2s(0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, 0x00) | |
| LK_PIC_SIZE_320 = a2s(0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, 0x11) | |
| LK_PIC_SIZE_160 = a2s(0x56, 0x00, 0x31, 0x05, 0x04, 0x01, 0x00, 0x19, 0x22) | |
| LK_PIC_SIZE_RE = a2s(0x76, 0x00, 0x31, 0x00, 0x00) | |
| LK_BAUD_RATE = a2s(0x56, 0x00, 0x24, 0x03, 0x01) | |
| LK_BAUD_RATE_RE = a2s(0x76, 0x00, 0x24, 0x00, 0x00) | |
| attr_reader :serial | |
| def grab_pic | |
| SerialPort.open("/dev/ttyACM0", 38400, 8, 1, SerialPort::NONE) do |ser| | |
| @serial = ser | |
| ser.read_timeout = 100 #ms | |
| info "reseting" | |
| reset | |
| sleep 2 | |
| info "picture" | |
| take_picture | |
| info "size" | |
| check_size do |size| | |
| fetch_data( size ) do |data| | |
| File.open( 'output.jpg', 'w' ) do |f| | |
| info "write into #{f.path}" | |
| f << data | |
| debug "done" | |
| end | |
| end | |
| end | |
| end | |
| end | |
| def reset | |
| serial.flush_input | |
| serial.write LK_RESET | |
| sleep 0.1 | |
| check_response_with! LK_RESET_RE | |
| end | |
| def stop | |
| serial.flush_input | |
| serial.write LK_STOP | |
| sleep 0.1 | |
| check_response_with! LK_STOP_RE | |
| end | |
| def check_response_with! expect | |
| serial.read( expect.size ).tap do |res| | |
| if res != expect | |
| debug "fail, got: #{res.inspect}" | |
| debug " expect: #{expect.inspect}" | |
| raise "failed" | |
| else | |
| debug "done" | |
| end | |
| end | |
| end | |
| def set_size( size ) | |
| serial.flush_input | |
| serial.write LK_PIC_SIZE_640 | |
| sleep 0.1 | |
| check_response_with! LK_PIC_SIZE_RE | |
| end | |
| def take_picture | |
| serial.flush_input | |
| serial.write LK_PICTURE | |
| sleep 0.5 | |
| check_response_with! LK_PICTURE_RE | |
| end | |
| def check_size | |
| serial.flush_input | |
| serial.write LK_JPEGSIZE | |
| sleep 0.5 | |
| check_response_with! LK_JPEGSIZE_RE | |
| xh = serial.read(1).unpack('C*').first | |
| xl = serial.read(1).unpack('C*').first | |
| (xh * 256 + xl).tap do |size| | |
| yield size if block_given? | |
| end | |
| end | |
| def fetch_data size | |
| info "fetch JPEG data (#{size}byte)" | |
| kh = (size >> 8) & 0xFF | |
| kl = size & 0xFF | |
| serial.flush_input | |
| serial.write LK_READPICTURE + self.class.a2s(kh, kl) + LK_PICTURE_TIME | |
| sleep 0.05 | |
| debug "check ready signal" | |
| check_response_with! LK_READPICTURE_RE | |
| debug "begin reading JPEG" | |
| progress_bar = ProgressBar.create( | |
| :format => '%a %bᗧ%i %p%% %t', | |
| :progress_mark => ' ', | |
| :remainder_mark => '・' | |
| ) | |
| picture = "" | |
| read_size = 0 | |
| while true do | |
| chunk = serial.read(2) | |
| read_size += chunk.size | |
| picture += chunk | |
| progress_bar.progress = read_size.to_f / size * 100 | |
| break if chunk == JPEG_END | |
| end | |
| progress_bar.clear | |
| debug "#{read_size} of #{size} read" | |
| debug "data size: #{picture.size}" | |
| picture.tap do | |
| debug "done reading" | |
| yield picture if block_given? | |
| end | |
| end | |
| private | |
| def info msg | |
| puts section << msg | |
| end | |
| def section | |
| "---> " | |
| end | |
| def debug msg | |
| puts indent << msg.black | |
| end | |
| def indent | |
| " " * 5 | |
| end | |
| end | |
| Y201Grab.new.grab_pic |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment