#!/usr/bin/python
# j4cDAC "sitter"
#
# Copyright 2012 Jacob Potter
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
import socket
import time
import struct
def pack_point(x, y, r, g, b, i = -1, u1 = 0, u2 = 0, flags = 0):
"""Pack some color values into a struct dac_point.
Values must be specified for x, y, r, g, and b. If a value is not
passed in for the other fields, i will default to max(r, g, b); the
rest default to zero.
"""
if i < 0:
i = max(r, g, b)
return struct.pack(" len(self.buf):
self.buf += self.conn.recv(4096)
obuf = self.buf
self.buf = obuf[l:]
return obuf[:l]
def readresp(self, cmd):
"""Read a response from the DAC."""
data = self.read(22)
response = data[0]
cmdR = data[1]
status = Status(data[2:])
# status.dump()
if cmdR != cmd:
raise ProtocolError("expected resp for %r, got %r"
% (cmd, cmdR))
if response != "a":
raise ProtocolError("expected ACK, got %r"
% (response, ))
self.last_status = status
return status
def __init__(self, macstr, bp):
self.macstr = macstr
self.firmware_string = "-"
self.got_broadcast(bp)
try:
t1 = time.time()
self.connect(self.last_broadcast.ip[0])
t = time.time() - t1
self.conn_status = "ok (%d ms)" % (t * 500)
if self.last_broadcast.sw_rev < 2:
self.firmware_string = "(old)"
else:
self.conn.sendall('v')
self.firmware_string = self.read(32).replace("\x00", " ").strip()
except e:
self.conn_status = str(e)
def connect(self, host, port = 7765):
"""Connect to the DAC over TCP."""
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.settimeout(0.2)
conn.connect((host, port))
self.conn = conn
self.buf = ""
# Read the "hello" message
first_status = self.readresp("?")
first_status.dump()
def begin(self, lwm, rate):
cmd = struct.pack(">", self.update_selection)
def update_selection(self, lb=None):
if self.dac_display:
try:
dac_obj = self.dac_list[self.index(ACTIVE)]
except:
return
self.dac_display.display_dac(dac_obj)
def got_packet(self, bp):
macstr = bp.macstr()
if macstr not in self.dac_macstr_map:
new_dac = DAC(macstr, bp)
self.insert(END, macstr[6:])
self.dac_list.append(new_dac)
self.dac_macstr_map[macstr] = new_dac
dac_obj = new_dac
else:
dac_obj = self.dac_macstr_map[macstr]
dac_obj.got_broadcast(bp)
if len(self.dac_list) == 1:
self.selection_set(0)
self.update_selection()
def check_on_dac():
if time.time() - dac_obj.last_broadcast_time < 2:
return
idx = self.dac_list.index(dac_obj)
self.dac_list.remove(dac_obj)
del self.dac_macstr_map[macstr]
self.delete(idx)
self.dac_display.display_none()
self.after(2000, check_on_dac)
# Set up the basic window
root = Tk()
root.title("Ether Dream")
root.resizable(FALSE, FALSE)
frame = Frame(root)
frame.grid()
disp = DacDisplay(root)
disp.grid(row=0, column=1, padx=5, pady=5)
tracker = DacTracker(root, height=22)
tracker.grid(row=0, column=0, padx=5, pady=5)
tracker.dac_display = disp
# Set up queue checker
packet_queue = Queue.Queue()
def queue_check():
try:
while True:
data, addr = packet_queue.get_nowait()
tracker.got_packet(BroadcastPacket(data, addr))
except Queue.Empty:
root.after(100, queue_check)
root.after(100, queue_check)
# Set up listening socket and thread
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", 7654))
def socket_thread():
while True:
packet_queue.put(s.recvfrom(1024))
thread.start_new(socket_thread, ())
root.mainloop()