package org.openpnp.spi.base;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.swing.Icon;
import org.openpnp.CameraListener;
import org.openpnp.ConfigurationListener;
import org.openpnp.gui.support.Icons;
import org.openpnp.model.AbstractModelObject;
import org.openpnp.model.Configuration;
import org.openpnp.model.LengthUnit;
import org.openpnp.model.Location;
import org.openpnp.spi.Camera;
import org.openpnp.spi.Head;
import org.openpnp.spi.VisionProvider;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
public abstract class AbstractCamera extends AbstractModelObject implements Camera {
@Attribute
protected String id;
@Attribute(required = false)
protected String name;
@Attribute
protected Looking looking = Looking.Down;
@Element
protected Location unitsPerPixel = new Location(LengthUnit.Millimeters);
@Element(required = false)
protected VisionProvider visionProvider;
@Attribute(required = false)
protected long settleTimeMs = 250;
protected Set<ListenerEntry> listeners = Collections.synchronizedSet(new HashSet<>());
protected Head head;
protected Integer width;
protected Integer height;
private boolean headSet = false;
public AbstractCamera() {
this.id = Configuration.createId("CAM");
this.name = getClass().getSimpleName();
Configuration.get().addListener(new ConfigurationListener.Adapter() {
@Override
public void configurationLoaded(Configuration configuration) throws Exception {
if (visionProvider != null) {
visionProvider.setCamera(AbstractCamera.this);
}
}
});
}
@Override
public String getId() {
return id;
}
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
firePropertyChange("name", null, name);
}
@Override
public Head getHead() {
return head;
}
@Override
public void setHead(Head head) {
if (this.headSet) {
throw new Error("Can't change head on camera " + this);
}
this.head = head;
this.headSet = true;
}
@Override
public Location getUnitsPerPixel() {
return unitsPerPixel;
}
@Override
public void setUnitsPerPixel(Location unitsPerPixel) {
this.unitsPerPixel = unitsPerPixel;
}
@Override
public void setLooking(Looking looking) {
this.looking = looking;
firePropertyChange("looking", null, looking);
}
@Override
public Looking getLooking() {
return looking;
}
@Override
public void startContinuousCapture(CameraListener listener, int maximumFps) {
listeners.add(new ListenerEntry(listener, maximumFps));
}
@Override
public void stopContinuousCapture(CameraListener listener) {
listeners.remove(new ListenerEntry(listener, 0));
}
@Override
public void setVisionProvider(VisionProvider visionProvider) {
this.visionProvider = visionProvider;
visionProvider.setCamera(this);
}
@Override
public VisionProvider getVisionProvider() {
return visionProvider;
}
public BufferedImage settleAndCapture() {
try {
Thread.sleep(getSettleTimeMs());
}
catch (Exception e) {
}
return capture();
}
protected void broadcastCapture(BufferedImage img) {
for (ListenerEntry listener : new ArrayList<>(listeners)) {
if (listener.lastFrameSent < (System.currentTimeMillis()
- (1000 / listener.maximumFps))) {
listener.listener.frameReceived(img);
listener.lastFrameSent = System.currentTimeMillis();
}
}
}
public long getSettleTimeMs() {
return settleTimeMs;
}
public void setSettleTimeMs(long settleTimeMs) {
this.settleTimeMs = settleTimeMs;
}
@Override
public Icon getPropertySheetHolderIcon() {
return Icons.captureCamera;
}
@Override
public void moveTo(Location location) throws Exception {
moveTo(location, getHead().getMachine().getSpeed());
}
@Override
public void moveToSafeZ() throws Exception {
moveToSafeZ(getHead().getMachine().getSpeed());
}
protected class ListenerEntry {
public CameraListener listener;
public int maximumFps;
public long lastFrameSent;
public ListenerEntry(CameraListener listener, int maximumFps) {
this.listener = listener;
this.maximumFps = maximumFps;
}
@Override
public int hashCode() {
return listener.hashCode();
}
@Override
public boolean equals(Object obj) {
return obj.equals(listener);
}
}
}