Преглед на файлове

GRID+ v2 and swing

Started porting the program to the swing library and adding support for
GRID+ v2. Also imported RXTX using Maven.
Tankernn преди 8 години
родител
ревизия
c1264314b4

+ 52 - 0
.gitignore

@@ -0,0 +1,52 @@
+target/
+.metadata
+bin/
+tmp/
+lib/
+*.tmp
+*.bak
+*.swp
+*~.nib
+local.properties
+.settings/
+.loadpath
+.recommenders
+
+# Eclipse Core
+.project
+
+# External tool builders
+.externalToolBuilders/
+
+# Locally stored "Eclipse launch configurations"
+*.launch
+
+# PyDev specific (Python IDE for Eclipse)
+*.pydevproject
+
+# CDT-specific (C/C++ Development Tooling)
+.cproject
+
+# JDT-specific (Eclipse Java Development Tools)
+.classpath
+
+# Java annotation processor (APT)
+.factorypath
+
+# PDT-specific (PHP Development Tools)
+.buildpath
+
+# sbteclipse plugin
+.target
+
+# Tern plugin
+.tern-project
+
+# TeXlipse plugin
+.texlipse
+
+# STS (Spring Tool Suite)
+.springBeans
+
+# Code Recommenders
+.recommenders/

+ 0 - 6
lib/lib_location.txt

@@ -1,6 +0,0 @@
-http://fizzed.com/oss/rxtx-for-java
-Required files in this folder:
-
-  RXTXcomm.jar
-  rxtxParallel.dll
-  rxtxSerial.dll

+ 46 - 0
pom.xml

@@ -0,0 +1,46 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>eu.tankernn.camsucks</groupId>
+	<artifactId>CamSucks</artifactId>
+	<version>0.0.1</version>
+	<name>CAM Sucks</name>
+	<description>An alternative app for controlling the NZXT GRID+.</description>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.fazecast</groupId>
+			<artifactId>jSerialComm</artifactId>
+			<version>1.3.11</version>
+		</dependency>
+		<!-- https://mvnrepository.com/artifact/org.snmp4j/snmp4j -->
+		<dependency>
+			<groupId>org.snmp4j</groupId>
+			<artifactId>snmp4j</artifactId>
+			<version>2.5.5</version>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<sourceDirectory>src</sourceDirectory>
+		<resources>
+			<resource>
+				<directory>src</directory>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+		</resources>
+		<plugins>
+			<plugin>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.6.1</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 111 - 65
src/camsucks/CAMSucks.java

@@ -1,87 +1,133 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
 package camsucks;
 
-import camsucks.model.ComputerModel;
-import javafx.application.Application;
-import javafx.fxml.FXMLLoader;
-import javafx.scene.Parent;
-import javafx.scene.Scene;
-import javafx.scene.image.Image;
-import javafx.stage.Stage;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
 
 /**
- *  This Project aims to replace the default software made for the GRID+ Controller; CAM
+ * This Project aims to replace the default software made for the GRID+
+ * Controller; CAM
  * <p>
  * Software used for this project
  * <p>
  * <ul>
- * <li> The reverse engineering of the GRID+ communication was done by rizvanrp, their site is no longer available but here is a screenshot of their article on the GRID+ http://research.domaintools.com/research/screenshot-history/rizvanrp.com/#0
- * <li> The aim is to be able to control the fan speed of the fans connected to a GRID controller according to the temperature of the CPU Packages
- * <li> The project uses a Communicator class that has been created by Henry Poon @ https://blog.henrypoon.com/ 
- * <li> With the help of this class the communication with the GRID+ controller is handled
- * <li> The sensor data is read with the help of the jWMI class made by Henry Ranch @ http://henryranch.net
- * <li> This class communicates with an external program called openhardwaremonitor @ http://openhardwaremonitor.org/
+ * <li>The reverse engineering of the GRID+ communication was done by rizvanrp,
+ * their site is no longer available but here is a screenshot of their article
+ * on the GRID+
+ * http://research.domaintools.com/research/screenshot-history/rizvanrp.com/#0
+ * <li>The aim is to be able to control the fan speed of the fans connected to a
+ * GRID controller according to the temperature of the CPU Packages
+ * <li>The project uses a Communicator class that has been created by Henry
+ * Poon @ https://blog.henrypoon.com/
+ * <li>With the help of this class the communication with the GRID+ controller
+ * is handled
+ * <li>The sensor data is read with the help of the jWMI class made by Henry
+ * Ranch @ http://henryranch.net
+ * <li>This class communicates with an external program called
+ * openhardwaremonitor @ http://openhardwaremonitor.org/
  * </ul>
  * <p>
  * 
- *  Currently monitoring is a bit bugged and is disabled by default but can be turned on with a checkbox.
+ * Currently monitoring is a bit bugged and is disabled by default but can be
+ * turned on with a checkbox.
  * <p>
- *  Future plans and TODOs:
+ * Future plans and TODOs:
  * <p>
  * <ul>
- * <li>     Make it possible to control fans according to GPU or CPU  or Both temperatures (seems easy enough).
- * <li>     Add Integral control to achieve full PI control (Before this can happen a the time constant of the system must be defined reliably .
- * <li>     Make program not crash after/during system sleep/hibernation.
- * <li>     Find a way to compile program and not get security warnings (because of the filewriter in the jWMI class).
- * <li>     Make a config file to save user setting in.
+ * <li>Make it possible to control fans according to GPU or CPU or Both
+ * temperatures (seems easy enough).
+ * <li>Add Integral control to achieve full PI control (Before this can happen a
+ * the time constant of the system must be defined reliably .
+ * <li>Make program not crash after/during system sleep/hibernation.
+ * <li>Find a way to compile program and not get security warnings (because of
+ * the filewriter in the jWMI class).
+ * <li>Make a config file to save user setting in.
  * </ul>
  * <p>
  * 
  * 
  * @author Roel
  */
-public class CAMSucks extends Application {
-
-    @Override
-    public void start(Stage stage) throws Exception {
-        
-        // Model
-        ComputerModel model = new ComputerModel("COM3");
-        
-        // View
-        FXMLLoader loader = new FXMLLoader();
-        loader.setLocation(getClass().getResource("FXMLView.fxml"));
-        Parent root = loader.load();
-        
-        // Controller
-        FXMLViewController controller = loader.getController();
-        controller.setModel(model);
-   
-        //Scene
-        Scene scene = new Scene(root);
-        setUserAgentStylesheet(STYLESHEET_CASPIAN);
-        stage.setResizable(false);
-        stage.setTitle("CAM Sucks!");
-        stage.getIcons().add(new Image(getClass().getResourceAsStream("NoCAMIcon.jpg")));
-        stage.setScene(scene);
-        stage.show();
-        
-        stage.setOnCloseRequest(event -> {
-            model.getGrid().disconnect();
-            System.exit(0);
-        });     
-    }
-
-    /**
-     * 
-     * @param args the command line arguments
-     */
-    public static void main(String[] args)  {
-        launch(args);
-    }
+public class CAMSucks extends JFrame implements WindowListener {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+	
+	CAMSucksPanel panel = new CAMSucksPanel();
+
+	public CAMSucks() {
+		start();
+	}
+
+	public void start() {
+		this.add(panel);
+
+		setResizable(true);
+		setTitle("CAM Sucks!");
+		try {
+			setIconImage(ImageIO.read(getClass().getResourceAsStream("NoCAMIcon.jpg")));
+		} catch (IOException e1) {
+			e1.printStackTrace();
+		}
+		pack();
+		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+		addWindowListener(this);
+	}
+
+	/**
+	 * 
+	 * @param args the command line arguments
+	 */
+	public static void main(String[] args) {
+		CAMSucks cams = new CAMSucks();
+		cams.setVisible(true);
+	}
+
+	@Override
+	public void windowOpened(WindowEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void windowClosing(WindowEvent e) {
+		panel.getModel().getGrid().disconnect();
+		System.exit(0);
+	}
+
+	@Override
+	public void windowClosed(WindowEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void windowIconified(WindowEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void windowDeiconified(WindowEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void windowActivated(WindowEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	public void windowDeactivated(WindowEvent e) {
+		// TODO Auto-generated method stub
+		
+	}
 
 }

+ 283 - 0
src/camsucks/CAMSucksPanel.java

@@ -0,0 +1,283 @@
+package camsucks;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.text.DecimalFormat;
+import java.util.Arrays;
+import java.util.stream.IntStream;
+
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+
+import camsucks.model.ComputerModel;
+
+/**
+ * This class is the controller of this Project. It initializes the Interactive
+ * UI elements When its model is set it adds values to certain UI elements and
+ * starts a pollAndCompute thread
+ *
+ *
+ * @author Roel
+ */
+public class CAMSucksPanel extends JPanel implements Runnable {
+
+	/**
+	 * 
+	 */
+	private static final long serialVersionUID = 1L;
+
+	private Thread t;
+
+	private ComputerModel model;
+
+	private String[] fanColumns = { "#", "Voltage", "Current", "RPM" };
+	private String[][] fanData;
+	private JTable fanTable = new JTable(fanData, fanColumns);
+
+	private JTextField targetRPM = new JTextField();
+
+	private JTextField targetCPUTemp = new JTextField();
+
+	private JTextField maxCPUTemp = new JTextField();
+
+	private JTextField targetGPUTemp = new JTextField();
+
+	private JTextField maxGPUTemp = new JTextField();
+
+	private JTextField minRPM = new JTextField();
+
+	private JComboBox<String> portMap = new JComboBox<>();
+
+	private JCheckBox manualCheck = new JCheckBox("Manual");
+
+	private JSlider manualSlider = new JSlider();
+
+	// private JTabbedPane MonitorTab;
+
+	private JLabel CPULabel = new JLabel("CPU preferred");
+
+	private JLabel CPULabelMax = new JLabel("CPU max");
+
+	private JLabel GPULabel = new JLabel("GPU preferred");
+
+	private JLabel GPULabelMax = new JLabel("GPU max");
+
+	private JLabel PowerLabel = new JLabel("Power");
+
+	private JLabel[] VoltageLabels;
+
+	private JLabel[] AMPLabels;
+
+	private JLabel[] RPMLabels;
+	// </editor-fold>
+
+	/*
+	 * private void closeMonitor(Event event) {
+	 * 
+	 * if (MonitorTab.isSelected() && monitorCheck.isSelected() ) {
+	 * //System.out.println(" opened monitor"); model.setExtraPoll(true);
+	 * 
+	 * } else {
+	 * 
+	 * //System.out.println(" open configure"); model.setExtraPoll(false); }
+	 * 
+	 * }
+	 */
+	private void setTargetRPM(ActionEvent event) {
+		double dTargetRPM = Double.parseDouble(targetRPM.getText());
+
+		getModel().setTargetRPM(dTargetRPM);
+
+		// System.out.println(model.getTargetRPM());
+	}
+
+	private void setTargetCPUTemp(ActionEvent event) {
+		double dTargetTemp = Double.parseDouble(targetCPUTemp.getText());
+
+		getModel().setTargetCPUTemp(dTargetTemp);
+
+		// System.out.println(model.getTargetTemp());
+	}
+
+	private void setTargetGPUTemp(ActionEvent event) {
+		double dTargetTemp = Double.parseDouble(targetGPUTemp.getText());
+
+		getModel().setTargetGPUTemp(dTargetTemp);
+
+		// System.out.println(model.getTargetTemp());
+	}
+
+	private void setMinRPM(ActionEvent event) {
+		int dMinRPM = Integer.parseInt(minRPM.getText());
+
+		getModel().setMinRPM(dMinRPM);
+
+		// System.out.println(model.getMaxTemp());
+	}
+
+	private void setMaxCPUTemp(ActionEvent event) {
+		double dMaxTemp = Double.parseDouble(maxCPUTemp.getText());
+
+		getModel().setMaxCPUTemp(dMaxTemp);
+
+		// System.out.println(model.getMaxTemp());
+	}
+
+	private void setMaxGPUTemp(ActionEvent event) {
+		double dMaxTemp = Double.parseDouble(maxGPUTemp.getText());
+
+		getModel().setMaxGPUTemp(dMaxTemp);
+
+		// System.out.println(model.getMaxTemp());
+	}
+
+	private void setPort(ItemEvent event) {
+
+		String selectedPort = (String) portMap.getSelectedItem();
+
+		getModel().getGrid().disconnect();
+
+		getModel().setGrid(selectedPort);
+
+	}
+
+	public CAMSucksPanel() {
+		VoltageLabels = IntStream.range(0, 6).mapToObj(i -> new JLabel("V " + i)).toArray(i -> new JLabel[i]);
+		AMPLabels = IntStream.range(0, 6).mapToObj(i -> new JLabel("AMP " + i)).toArray(i -> new JLabel[i]);
+		RPMLabels = IntStream.range(0, 6).mapToObj(i -> new JLabel("RPM " + i)).toArray(i -> new JLabel[i]);
+
+		for (JLabel l : VoltageLabels)
+			this.add(l);
+		for (JLabel l : AMPLabels)
+			this.add(l);
+		for (JLabel l : RPMLabels)
+			this.add(l);
+
+		this.add(fanTable);
+
+		// MonitorTab.setOnSelectionChanged(this::closeMonitor);
+
+		targetRPM.addActionListener(this::setTargetRPM);
+
+		targetCPUTemp.addActionListener(this::setTargetCPUTemp);
+
+		maxCPUTemp.addActionListener(this::setMaxCPUTemp);
+
+		targetGPUTemp.addActionListener(this::setTargetGPUTemp);
+
+		maxGPUTemp.addActionListener(this::setMaxGPUTemp);
+
+		minRPM.addActionListener(this::setMinRPM);
+
+		//manualCheck.addActionListener(this::setManual);
+
+		manualSlider.setMaximum(100);
+
+		manualSlider.setMinimum(0);
+
+//		manualSlider.addChangeListener(new ChangeListener() {
+//
+//			@Override
+//			public void stateChanged(ChangeEvent e) {
+//				manualSpeed(e);
+//			}
+//		});
+
+		portMap.addItemListener(new ItemListener() {
+
+			@Override
+			public void itemStateChanged(ItemEvent e) {
+				setPort(e);
+			}
+		});
+
+	}
+
+	/**
+	 * This method sets the model for this controller. After the model is set
+	 * certain UI elements are updated Finally a pollAndCompute Thread is
+	 * started
+	 *
+	 * @param model the model to set
+	 */
+	public void setModel(ComputerModel model) {
+		this.model = model;
+
+		portMap.removeAllItems();
+		for (String key : model.getGrid().getCommunicator().getPortMap().keySet()) {
+			portMap.addItem(key);
+		}
+
+		maxCPUTemp.setText(Double.toString(model.getMaxCPUTemp()));
+		maxGPUTemp.setText(Double.toString(model.getMaxGPUTemp()));
+
+		targetRPM.setText(Double.toString(model.getTargetRPM()));
+
+		targetCPUTemp.setText(Double.toString(model.getTargetCPUTemp()));
+		targetGPUTemp.setText(Double.toString(model.getTargetGPUTemp()));
+
+		minRPM.setText(Double.toString(model.getMinRPM()));
+
+		updateProperties();
+
+		t = new Thread(this);
+		t.setDaemon(true);
+		t.start();
+	}
+
+	/**
+	 * This method updates the values of some UI elements and binds properties
+	 * to others
+	 *
+	 */
+	public void updateProperties() {
+		DecimalFormat df = new DecimalFormat("#.##");
+
+		CPULabel.setText(df.format(getModel().getSensor().getCPUTemp()) + " °C");
+		PowerLabel.setText(df.format(getModel().getGrid().getTotalWattage()) + " W");
+		CPULabelMax.setText(df.format(getModel().getSensor().getCpuMax()) + " °C Max");
+		GPULabel.setText(df.format(getModel().getSensor().getGPUTemp()) + " °C");
+		GPULabelMax.setText(df.format(getModel().getSensor().getGpuMax()) + " °C Max");
+
+		String[] indices = IntStream.range(0, 6).mapToObj(Integer::toString).toArray(String[]::new);
+		String[] voltages = Arrays.stream(getModel().getGrid().getVoltage()).mapToObj(df::format).toArray(String[]::new);
+		String[] rpms = Arrays.stream(getModel().getGrid().getFanRPM()).mapToObj(df::format).toArray(String[]::new);
+		String[] currents = Arrays.stream(getModel().getGrid().getFanAMP()).mapToObj(df::format).toArray(String[]::new);
+
+		fanData = new String[][] { indices, voltages, rpms, currents };
+		System.out.println(Arrays.deepToString(fanData));
+	}
+
+	@Override
+	public void run() {
+		while (!t.isInterrupted()) {
+			getModel().poll();
+
+			new Thread((() -> {
+				updateProperties();
+			})).start();
+			
+			if (!getModel().isManual()) {
+				getModel().compute();
+			}
+
+			try {
+				Thread.sleep(1000);
+			} catch (InterruptedException ex) {
+				System.out.println("Thread got interrupted");
+				return;
+			}
+		}
+
+	}
+
+	public ComputerModel getModel() {
+		return model;
+	}
+}

+ 0 - 96
src/camsucks/FXMLView.fxml

@@ -1,96 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<?import java.lang.*?>
-<?import java.util.*?>
-<?import javafx.scene.*?>
-<?import javafx.scene.control.*?>
-<?import javafx.scene.layout.*?>
-
-<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="212.0" prefWidth="231.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="camsucks.FXMLViewController">
-   <children>
-      <AnchorPane>
-         <children>
-            <TabPane fx:id="TapPane" prefHeight="211.0" prefWidth="231.0" tabClosingPolicy="UNAVAILABLE">
-              <tabs>
-                <Tab fx:id="ConfigureTab" text="Configure">
-                  <content>
-                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="164.0" prefWidth="335.0">
-                           <children>
-                              <Label layoutX="8.0" layoutY="8.0" text="Target Fan Percentage" />
-                              <Label layoutX="8.0" layoutY="29.0" text="Minimum Fan Percentage" />
-                              <Label layoutX="8.0" layoutY="57.0" text="Target Temperature" />
-                              <Label layoutX="127.0" layoutY="57.0" text="CPU" />
-                              <Label layoutX="127.0" layoutY="82.0" text="GPU" />
-                              <Label layoutX="8.0" layoutY="107.0" text="Preferred Maximum" />
-                              <Label layoutX="127.0" layoutY="107.0" text="CPU" />
-                              <Label layoutX="127.0" layoutY="132.0" text="GPU" />
-                              <Label layoutX="8.0" layoutY="158.0" text="COM Port" />
-                              <TextField fx:id="targetRPM" layoutX="161.0" layoutY="4.0" prefHeight="25.0" prefWidth="66.0" />
-                              <TextField fx:id="minRPM" layoutX="161.0" layoutY="28.0" prefHeight="25.0" prefWidth="65.0" />
-                              <TextField fx:id="targetCPUTemp" layoutX="161.0" layoutY="53.0" prefHeight="25.0" prefWidth="65.0" />
-                              <TextField fx:id="targetGPUTemp" layoutX="161.0" layoutY="78.0" prefHeight="25.0" prefWidth="65.0" />
-                              <TextField fx:id="maxCPUTemp" layoutX="161.0" layoutY="103.0" prefHeight="25.0" prefWidth="65.0" />
-                              <TextField fx:id="maxGPUTemp" layoutX="161.0" layoutY="128.0" prefHeight="25.0" prefWidth="65.0" />
-                              <ChoiceBox fx:id="portMap" layoutX="161.0" layoutY="153.0" prefHeight="25.0" prefWidth="65.0" />
-                           </children>
-                        </AnchorPane>
-                  </content>
-                </Tab>
-                  <Tab closable="false" text="Manual">
-                    <content>
-                      <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
-                           <children>
-                              <CheckBox fx:id="manualCheck" layoutX="14.0" layoutY="14.0" mnemonicParsing="false" text="Manual" />
-                              <Slider fx:id="manualSlider" layoutX="15.0" layoutY="86.0" prefHeight="13.0" prefWidth="200.0" AnchorPane.leftAnchor="15.0" />
-                              <Label layoutX="13.0" layoutY="56.0" text="Fan Speed" />
-                              <Label layoutX="14.0" layoutY="72.0" text="0%" />
-                              <Label layoutX="103.0" layoutY="72.0" text="50%" />
-                              <Label layoutX="193.0" layoutY="72.0" text="100%" />
-                              <Label layoutX="11.0" layoutY="114.0" prefHeight="42.0" prefWidth="205.0" text="This is free software. If you paid for this software you got scammed." wrapText="true" />
-                           </children></AnchorPane>
-                    </content>
-                  </Tab>
-                <Tab fx:id="MonitorTab" text="Monitor">
-                  <content>
-                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="370.0" prefWidth="613.0">
-                           <children>
-                              <Label layoutX="14.0" layoutY="37.0" prefHeight="17.0" prefWidth="63.0" text="FAN #1" />
-                              <Label layoutX="14.0" layoutY="54.0" prefHeight="17.0" prefWidth="63.0" text="FAN #2" />
-                              <Label layoutX="14.0" layoutY="71.0" prefHeight="17.0" prefWidth="63.0" text="FAN #2" />
-                              <Label layoutX="14.0" layoutY="88.0" prefHeight="17.0" prefWidth="63.0" text="FAN #4" />
-                              <Label layoutX="14.0" layoutY="105.0" prefHeight="17.0" prefWidth="63.0" text="FAN #5" />
-                              <Label layoutX="14.0" layoutY="122.0" prefHeight="17.0" prefWidth="63.0" text="FAN #6" />
-                              <Label fx:id="RPMLabel1" layoutX="93.0" layoutY="37.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="RPMLabel2" layoutX="93.0" layoutY="54.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="RPMLabel3" layoutX="93.0" layoutY="71.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="RPMLabel4" layoutX="93.0" layoutY="88.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="RPMLabel5" layoutX="93.0" layoutY="105.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="RPMLabel6" layoutX="93.0" layoutY="122.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel1" layoutX="156.0" layoutY="37.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel2" layoutX="156.0" layoutY="54.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel3" layoutX="156.0" layoutY="71.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel4" layoutX="156.0" layoutY="88.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel5" layoutX="156.0" layoutY="105.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel6" layoutX="156.0" layoutY="122.0" prefHeight="17.0" prefWidth="63.0" />
-                              <CheckBox fx:id="monitorCheck" layoutX="12.0" layoutY="15.0" mnemonicParsing="false" selected="true" text="Monitor" />
-                              <Label fx:id="RPMLabel11" layoutX="103.0" layoutY="47.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="AMPLabel11" layoutX="166.0" layoutY="47.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label layoutX="91.0" layoutY="15.0" prefHeight="17.0" prefWidth="63.0" text="Voltage" />
-                              <Label fx:id="VoltageLabel" layoutX="154.0" layoutY="15.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label layoutX="14.0" layoutY="137.0" prefHeight="17.0" prefWidth="63.0" text="CPU" />
-                              <Label fx:id="CPULabel" layoutX="93.0" layoutY="137.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="CPULabelMax" layoutX="156.0" layoutY="137.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label layoutX="14.0" layoutY="152.0" prefHeight="17.0" prefWidth="63.0" text="GPU" />
-                              <Label fx:id="GPULabel" layoutX="93.0" layoutY="152.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label fx:id="GPULabelMax" layoutX="156.0" layoutY="152.0" prefHeight="17.0" prefWidth="63.0" />
-                              <Label layoutX="14.0" layoutY="167.0" prefHeight="17.0" prefWidth="63.0" text="Power" />
-                              <Label fx:id="PowerLabel" layoutX="93.0" layoutY="167.0" prefHeight="17.0" prefWidth="63.0" />
-                           </children></AnchorPane>
-                  </content>
-                </Tab>
-              </tabs>
-            </TabPane>
-         </children>
-      </AnchorPane>
-   </children>
-</AnchorPane>

+ 0 - 369
src/camsucks/FXMLViewController.java

@@ -1,369 +0,0 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package camsucks;
-
-import camsucks.model.ComputerModel;
-import java.net.URL;
-import java.text.DecimalFormat;
-import java.util.ResourceBundle;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javafx.application.Platform;
-import javafx.event.ActionEvent;
-import javafx.event.Event;
-import javafx.fxml.FXML;
-import javafx.fxml.Initializable;
-import javafx.scene.control.CheckBox;
-import javafx.scene.control.ChoiceBox;
-import javafx.scene.control.Label;
-import javafx.scene.control.Slider;
-import javafx.scene.control.Tab;
-import javafx.scene.control.TextField;
-import javafx.scene.input.MouseEvent;
-
-/**
- * This class is the controller of this Project. It initialises the Interactive
- * UI elements When its model is set it adds values to certain UI elements and
- * starts a pollAndCompute thread
- *
- *
- * @author Roel
- */
-public class FXMLViewController implements Initializable, Runnable {
-
-    //<editor-fold defaultstate="collapsed" desc="Data members">
-    private Thread t;
-    
-    private ComputerModel model;
-
-    @FXML
-    private TextField targetRPM;
-    @FXML
-    private TextField targetCPUTemp;
-    @FXML
-    private TextField maxCPUTemp;
-    @FXML
-    private TextField targetGPUTemp;
-    @FXML
-    private TextField maxGPUTemp;
-    @FXML
-    private TextField minRPM;
-    @FXML
-    private ChoiceBox portMap;
-
-    @FXML
-    private CheckBox manualCheck;
-    @FXML
-    private Slider manualSlider;
-
-    @FXML
-    private Tab MonitorTab;
-
-    @FXML
-    private CheckBox monitorCheck;
-    @FXML
-    private Label VoltageLabel;
-    @FXML
-    private Label CPULabel;
-    @FXML
-    private Label CPULabelMax;
-    @FXML
-    private Label GPULabel;
-    @FXML
-    private Label GPULabelMax;
-    @FXML
-    private Label PowerLabel;
-    @FXML
-    private Label AMPLabel1;
-    @FXML
-    private Label AMPLabel2;
-    @FXML
-    private Label AMPLabel3;
-    @FXML
-    private Label AMPLabel4;
-    @FXML
-    private Label AMPLabel5;
-    @FXML
-    private Label AMPLabel6;
-
-    @FXML
-    private Label RPMLabel1;
-    @FXML
-    private Label RPMLabel2;
-    @FXML
-    private Label RPMLabel3;
-    @FXML
-    private Label RPMLabel4;
-    @FXML
-    private Label RPMLabel5;
-    @FXML
-    private Label RPMLabel6;
-//</editor-fold>
-
-    /*private void closeMonitor(Event event) {
-    
-    if (MonitorTab.isSelected() && monitorCheck.isSelected() ) {
-    //System.out.println(" opened monitor");
-    model.setExtraPoll(true);
-    
-    } else {
-    
-    //System.out.println(" open configure");
-    model.setExtraPoll(false);
-    }
-    
-    }*/
-    private void setTargetRPM(ActionEvent event) {
-        double dTargetRPM = Double.parseDouble(targetRPM.getText());
-
-        model.setTargetRPM(dTargetRPM);
-
-        //System.out.println(model.getTargetRPM());
-    }
-
-    private void setMonitor(ActionEvent event) {
-
-        if (monitorCheck.isSelected()) {
-
-            model.setExtraPoll(true);
-
-        } else {
-
-            model.setExtraPoll(false);
-
-        }
-
-    }
-
-    private void setManual(ActionEvent event) {
-
-        if (manualCheck.isSelected()) {
-
-            model.setManual(true);
-
-            model.setPercentageToSend((int) manualSlider.getValue());
-
-            //System.out.println("manual ");
-        } else {
-
-            model.setManual(false);
-            // System.out.println("auto");
-
-        }
-
-    }
-
-    private void manualSpeed(MouseEvent event) {
-
-        //System.out.println("miuse event");
-        if (model.isManual()) {
-
-            try {
-                model.setPercentageToSend((int) manualSlider.getValue());
-                Thread.sleep(50);
-            } catch (InterruptedException ex) {
-                Logger.getLogger(FXMLViewController.class.getName()).log(Level.SEVERE, null, ex);
-            }
-
-        }
-
-    }
-
-    private void setTargetCPUTemp(ActionEvent event) {
-        double dTargetTemp = Double.parseDouble(targetCPUTemp.getText());
-
-        model.setTargetCPUTemp(dTargetTemp);
-
-        //System.out.println(model.getTargetTemp());
-    }
-    
-    private void setTargetGPUTemp(ActionEvent event) {
-        double dTargetTemp = Double.parseDouble(targetGPUTemp.getText());
-
-        model.setTargetGPUTemp(dTargetTemp);
-
-        //System.out.println(model.getTargetTemp());
-    }
-
-    private void setMinRPM(ActionEvent event) {
-        int dMinRPM = Integer.parseInt(minRPM.getText());
-
-        model.setMinRPM(dMinRPM);
-
-        // System.out.println(model.getMaxTemp());
-    }
-    
-    private void setMaxCPUTemp(ActionEvent event) {
-        double dMaxTemp = Double.parseDouble(maxCPUTemp.getText());
-
-        model.setMaxCPUTemp(dMaxTemp);
-
-        // System.out.println(model.getMaxTemp());
-    }
-    
-    private void setMaxGPUTemp(ActionEvent event) {
-        double dMaxTemp = Double.parseDouble(maxGPUTemp.getText());
-
-        model.setMaxGPUTemp(dMaxTemp);
-
-        // System.out.println(model.getMaxTemp());
-    }
-
-    private void setPort(Event event) {
-
-        String selectedPort = portMap.getSelectionModel().selectedItemProperty().getValue().toString();
-
-        model.getGrid().disconnect();
-
-        model.setGrid(selectedPort);
-
-    }
-
-    @Override
-    public void initialize(URL url, ResourceBundle rb) {
-        //MonitorTab.setOnSelectionChanged(this::closeMonitor);
-
-        monitorCheck.setOnAction(this::setMonitor);
-
-        targetRPM.setOnAction(this::setTargetRPM);
-
-        targetCPUTemp.setOnAction(this::setTargetCPUTemp);
-
-        maxCPUTemp.setOnAction(this::setMaxCPUTemp);
-        
-        targetGPUTemp.setOnAction(this::setTargetGPUTemp);
-
-        maxGPUTemp.setOnAction(this::setMaxGPUTemp);
-        
-        minRPM.setOnAction(this::setMinRPM);
-
-        manualCheck.setOnAction(this::setManual);
-
-        manualSlider.setMax(100);
-
-        manualSlider.setMin(0);
-
-        manualSlider.setOnMouseReleased(this::manualSpeed);
-
-        portMap.setOnAction(this::setPort);
-
-    }
-
-    /**
-     * This method sets the model for this controller. After the model is set
-     * certain UI elements are updated Finally a pollAndCompute Thread is
-     * started
-     *
-     * @param model the model to set
-     */
-    public void setModel(ComputerModel model) {
-
-        this.model = model;
-        //this.model.setGrid("COM5");
-
-        for (Object key : model.getGrid().getCommunicator().getPortMap().keySet()) {
-            portMap.getItems().add(key);
-        }
-
-        maxCPUTemp.setText(Double.toString(model.getMaxCPUTemp()));
-        maxGPUTemp.setText(Double.toString(model.getMaxGPUTemp()));
-
-        targetRPM.setText(Double.toString(model.getTargetRPM()));
-
-        targetCPUTemp.setText(Double.toString(model.getTargetCPUTemp()));
-        targetGPUTemp.setText(Double.toString(model.getTargetGPUTemp()));
-
-        minRPM.setText(Double.toString(model.getMinRPM()));
-
-        updateProperties();
-
-        //pollAndCompute poll = new pollAndCompute(model);
-        t = new Thread(this);
-        t.setDaemon(true);
-        t.start();
-    }
-
-    /**
-     * This method updates the values of some UI elements and binds properties
-     * to others
-     *
-     */
-    public void updateProperties() {
-        
-        DecimalFormat df = new DecimalFormat("#.##");      
-        
-        CPULabel.setText(df.format(model.getSensor().getCPUTemp()) + " °C");
-        
-        PowerLabel.setText(df.format(model.getGrid().getTotalWattage()) + " W");;
-        
-        CPULabelMax.setText(df.format(model.getSensor().getCpuMax()) + " °C Max");
-        
-        GPULabel.setText(df.format(model.getSensor().getGPUTemp()) + " °C");
-        
-        GPULabelMax.setText(df.format(model.getSensor().getGpuMax()) + " °C Max");
-        
-        VoltageLabel.setText(df.format(model.getGrid().getVoltage()) + " V");
-        
-        (RPMLabel1).setText(df.format(model.getGrid().getFanRPM(1)) + " RPM");
-
-        (RPMLabel2).setText(df.format(model.getGrid().getFanRPM(2)) + " RPM");
-
-        (RPMLabel3).setText(df.format(model.getGrid().getFanRPM(3)) + " RPM");
-
-        (RPMLabel4).setText(df.format(model.getGrid().getFanRPM(4)) + " RPM");
-
-        (RPMLabel5).setText(df.format(model.getGrid().getFanRPM(5)) + " RPM");
-
-        (RPMLabel6).setText(df.format(model.getGrid().getFanRPM(6)) + " RPM");
-
-        (AMPLabel1).setText(df.format(model.getGrid().getFanAMP(1)) + " A");
-
-        (AMPLabel2).setText(df.format(model.getGrid().getFanAMP(2)) + " A");
-
-        (AMPLabel3).setText(df.format(model.getGrid().getFanAMP(3)) + " A");
-
-        (AMPLabel4).setText(df.format(model.getGrid().getFanAMP(4)) + " A");
-
-        (AMPLabel5).setText(df.format(model.getGrid().getFanAMP(5)) + " A");
-
-        (AMPLabel6).setText(df.format(model.getGrid().getFanAMP(6)) + " A");
-
-    }
-
-    @Override
-    public void run() {
-
-        while (true) {
-
-            long milis = System.currentTimeMillis();
-
-            //System.out.println("Polling...");
-
-            model.poll();
-
-            Platform.runLater(() -> {
-                updateProperties();
-            });
-
-            //System.out.println("Computing...");
-            if (!model.isManual()) {
-                model.compute();
-            }
-
-            model.updateFanSpeed();
-
-            try {
-                while (System.currentTimeMillis() - milis <= 1000) {
-                    Thread.sleep(50);
-                }
-            } catch (InterruptedException ex) {
-                System.out.println("Thread got interrupted");
-            }
-        }
-
-    }
-
-}

BIN
src/camsucks/NoCAMIcon.jpg


+ 246 - 332
src/camsucks/model/Communicator.java

@@ -1,346 +1,260 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
 package camsucks.model;
 
-import gnu.io.*;
+import static java.lang.Thread.sleep;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import static java.lang.Thread.sleep;
-import java.util.Enumeration;
 import java.util.HashMap;
 
+import com.fazecast.jSerialComm.SerialPort;
+
 /**
  * This class communicates with a serial com device
- * @author Henry Poon  @ https://blog.henrypoon.com/ 
- * Changes by Roel:     Removed all references to the GUI class from Henry Poon's original project.
- *                      Changed the event based serial read to a synchronised read after each write. 
- *                      Added a Buffer for the serial read so that the read data can easily be accessed by other classes
- *                      Completely rewritten the writeData method so that it works with the GRID+ controller
- *                      Added some getters and setters for the buffer
- *                      added a getter for the portMap so that the controller and view can access it
+ * 
+ * @author Henry Poon @ https://blog.henrypoon.com/ Changes by Roel: Removed all
+ *         references to the GUI class from Henry Poon's original project.
+ *         Changed the event based serial read to a synchronised read after each
+ *         write. Added a Buffer for the serial read so that the read data can
+ *         easily be accessed by other classes Completely rewritten the
+ *         writeData method so that it works with the GRID+ controller Added
+ *         some getters and setters for the buffer added a getter for the
+ *         portMap so that the controller and view can access it
  */
 public class Communicator {
 
-    //for containing the ports that will be found
-    private Enumeration ports = null;
-    //map the port names to CommPortIdentifiers
-    private HashMap portMap = new HashMap();
-    //this is the object that contains the opened port
-    private String selectedPort;
-    private CommPortIdentifier selectedPortIdentifier = null;
-    private SerialPort serialPort = null;
-
-    //input and output streams for sending and receiving data
-    private InputStream input = null;
-    private OutputStream output = null;
-
-    //just a boolean flag that i use for enabling
-    //and disabling buttons depending on whether the program
-    //is connected to a serial port or not
-    private boolean bConnected = false;
-
-    //the timeout value for connecting with the port
-    final static int TIMEOUT = 2000;
-
-    //some ascii values for for certain things
-    final static int SPACE_ASCII = 32;
-    final static int DASH_ASCII = 45;
-    final static int NEW_LINE_ASCII = 10;
-
-    //Buffer
-    private int leng;
-    private byte[] buffer;
-
-    //a string for recording what goes on in the program
-    String logText = "";
-
-    /**
-     *
-     * @param selectedPort This parameter is the string name of the port the communicator object should connect to
-     */
-    public Communicator(String selectedPort) {
-        this.selectedPort = selectedPort;
-    }
-
-    //search for all the serial ports
-    //pre: none
-    //post: adds all the found ports to a combo box on the GUI
-
-    /**
-     *
-     * This method searches for COM ports on the system and saves their Identifier in the hashmap portMap with their name as key.
-     * 
-     */
-    public void searchForPorts() {
-        ports = CommPortIdentifier.getPortIdentifiers();
-
-        while (ports.hasMoreElements()) {
-            CommPortIdentifier curPort = (CommPortIdentifier) ports.nextElement();
-
-            //get only serial ports
-            if (curPort.getPortType() == CommPortIdentifier.PORT_SERIAL) {
-                getPortMap().put(curPort.getName(), curPort);
-            }
-        }
-        //System.out.println(portMap);
-    }
-
-    //connect to the selected port in the combo box
-    //pre: ports are already found by using the searchForPorts method
-    //post: the connected comm port is stored in commPort, otherwise,
-    //an exception is generated
-
-    /**
-     *This method opens the COM port with port parameters: Baudrate: 4800; databits: 8; Stopbit: 1; parity: none; 
-     */
-    public void connect() {
-        selectedPortIdentifier = (CommPortIdentifier) getPortMap().get(selectedPort);
-
-        CommPort commPort = null;
-
-        try {
-            //the method below returns an object of type CommPort
-            commPort = selectedPortIdentifier.open("TigerControlPanel", TIMEOUT);
-            //the CommPort object can be casted to a SerialPort object
-            serialPort = (SerialPort) commPort;
-            serialPort.setSerialPortParams(4800, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
-            //for controlling GUI elements
-            setConnected(true);
-
-            //logging
-            logText = selectedPort + " opened successfully.";
-            System.out.println(logText);
-            //CODE ON SETTING BAUD RATE ETC OMITTED
-            //XBEE PAIR ASSUMED TO HAVE SAME SETTINGS ALREADY
-
-        } catch (PortInUseException e) {
-            logText = selectedPort + " is in use. (" + e.toString() + ")";
-
-            System.out.println(logText);
-        } catch (Exception e) {
-            logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
-            System.out.println(logText);
-        }
-    }
-
-    //open the input and output streams
-    //pre: an open port
-    //post: initialized intput and output streams for use to communicate data
-
-    /**
-     * This method initializes the serial IO stream,
-     * after the init is complete the method sends an initialize command to the GRID+ controller
-     * @return successful Boolean value which indicates whether the method was completed succesfuly
-     */
-    public boolean initIOStream() {
-        //return value for whather opening the streams is successful or not
-        boolean successful = false;
-
-        try {
-            //
-            input = serialPort.getInputStream();
-            output = serialPort.getOutputStream();
-
-            writeData(0Xc0);
-            successful = true;
-            return successful;
-        } catch (IOException e) {
-            logText = "I/O Streams failed to open. (" + e.toString() + ")";
-            System.out.println(logText);
-            return successful;
-        }
-    }
-
-    
-    /**
-     *This method disconnects the serial communication by first closing the serialPort and then closing the IOStreams
-     * 
-     * 
-     */
-    public void disconnect() {
-        //close the serial port
-        try {
-           
-            
-            //serialPort.removeEventListener();
-            serialPort.close();
-            input.close();
-            output.close();
-            setConnected(false);
-
-            logText = "Disconnected.";
-            System.out.println(logText);
-        } catch (IOException e) {
-            logText = "Failed to close " + serialPort.getName() + "(" + e.toString() + ")";
-            System.out.println(logText);
-        }
-    }
-
-    /**
-     *  Returns true if the connection is open
-     *  False if closed
-     * @return boolean value for the connection status
-     */
-    final public boolean getConnected() {
-        return bConnected;
-    }
-
-    /**
-     *Setter for the  boolean value for the connection status
-     * @param bConnected boolean value for the connection status
-     */
-    public void setConnected(boolean bConnected) {
-        this.bConnected = bConnected;
-    }
-
-    //what happens when data is received
-    //pre: serial event is triggered
-    //post: processing on the data it reads
-
-    /**
-     * This method reads data from the input stream and puts it in a buffer 
-     * after the data is read the method waits 50 msec to make sure a new command doesn't follow up to quickly
-     * This promotes stability in the program.
-     * 
-     * 
-     */
-    public void serialRead() throws InterruptedException {
-        try {
-            if (input.available() > 0) {
-                try {
-
-                    setBuffer(new byte[1024]);
-
-                    setLeng(input.read(getBuffer()));
-
-                    // Debug.
-                    /*System.out.println("Length: " + getLeng());
-            
-                    for (int itera = 0; itera < leng; itera++) {
-                    System.out.println("byte " + itera + ": " + Integer.toHexString(getBuffer(itera) & 0xFF));
-                    }*/
-                } catch (Exception e) {
-                    logText = "Failed to read data. (" + e.toString() + ")";
-                    System.out.println(logText);
-                }
-            } else {
-                logText = "Failed to read data. No data to read";
-                //System.out.println(logText);
-            }
-
-        } catch (IOException e) {
-            logText = "Failed to read data. (" + e.toString() + ")";
-            System.out.println(logText);
-        }
-        //This prevents commands from being send too soon  
-        sleep(50);
-    }
-
-    //method that can be called to send data
-    //pre: open serial port
-    //post: data sent to the other device
-
-    /**
-     * This method sends a single byte command over the serial communication afterwards the method calls the read method
-     * @param command a single byte command
-     */
-    public void writeData(int command) {
-        try {
-            output.write(command);
-            sleep(20);
-            serialRead();
-        } catch (Exception e) {
-            logText = "Failed to write data. (" + e.toString() + ")";
-            System.out.println(logText);
-
-        }
-    }
-
-    /**
-     *  This method sends a byte array command over the serial communication afterwards the method calls the read method
-     * @param command an array of bytes as a command
-     */
-    public void writeData(byte[] command) {
-        try {
-            output.write(command);
-            sleep(50);
-            serialRead();
-        } catch (Exception e) {
-            logText = "Failed to write data. (" + e.toString() + ")";
-            System.out.println(logText);
-
-        }
-    }
-
-    /**
-     * @return the leng
-     */
-    public int getLeng() {
-        return leng;
-    }
-
-    /**
-     * @param leng the leng to set
-     */
-    public void setLeng(int leng) {
-        this.leng = leng;
-    }
-
-    /**
-     * @return the buffer
-     */
-    public byte[] getBuffer() {
-        return buffer;
-    }
-
-    /**
-     *
-     * @param i 
-     * @return The value of the buffer at i
-     */
-    public byte getBuffer(int i) {
-        return buffer[i];
-    }
-
-    /**
-     *
-     * @return  The second to last byte of the buffer
-     */
-    public byte getSecondToLast() {
-        if (leng >= 2) {
-            return buffer[leng - 2];
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     *
-     * @return The last byte of the buffer
-     */
-    public byte getlast() {
-        if (leng >= 2) {
-            return buffer[leng - 1];
-        } else {
-            return 0;
-        }
-    }
-
-    /**
-     * @param buffer the buffer to set
-     */
-    public void setBuffer(byte[] buffer) {
-        this.buffer = buffer;
-    }
-
-    /**
-     * @return the portMap
-     */
-    public HashMap getPortMap() {
-        return portMap;
-    }
+	// for containing the ports that will be found
+	private SerialPort[] ports;
+	// map the port names to CommPortIdentifiers
+	private HashMap<String, SerialPort> portMap = new HashMap<>();
+	// this is the object that contains the opened port
+	private SerialPort serialPort = null;
+
+	// input and output streams for sending and receiving data
+	private InputStream input = null;
+	private OutputStream output = null;
+
+	// the timeout value for connecting with the port
+	final static int TIMEOUT = 2000;
+
+	// some ascii values for for certain things
+	final static int SPACE_ASCII = 32;
+	final static int DASH_ASCII = 45;
+	final static int NEW_LINE_ASCII = 10;
+
+	// Buffer
+	private int leng;
+	private byte[] buffer;
+
+	// a string for recording what goes on in the program
+	String logText = "";
+
+	// search for all the serial ports
+	// pre: none
+	// post: adds all the found ports to a combo box on the GUI
+
+	/**
+	 *
+	 * This method searches for COM ports on the system and saves their
+	 * Identifier in the hashmap portMap with their name as key.
+	 * 
+	 */
+	public void searchForPorts() {
+		ports = SerialPort.getCommPorts();
+
+		for (SerialPort p : ports) {
+			portMap.put(p.getSystemPortName(), p);
+		}
+	}
+
+	// connect to the selected port in the combo box
+	// pre: ports are already found by using the searchForPorts method
+	// post: the connected comm port is stored in commPort, otherwise,
+	// an exception is generated
+
+	/**
+	 * This method opens the COM port with port parameters: Baudrate: 4800;
+	 * databits: 8; Stopbit: 1; parity: none;
+	 * @param selectedPort 
+	 */
+	public void connect(String selectedPort) {
+
+		try {
+			serialPort = portMap.get(selectedPort);
+
+			serialPort.setBaudRate(4800);
+			serialPort.setNumDataBits(8);
+			serialPort.setNumStopBits(SerialPort.ONE_STOP_BIT);
+			serialPort.setParity(SerialPort.NO_PARITY);
+			serialPort.openPort();
+			initIOStream();
+
+			// logging
+			logText = selectedPort + " opened successfully.";
+			System.out.println(logText);
+
+			// CODE ON SETTING BAUD RATE ETC OMITTED
+			// XBEE PAIR ASSUMED TO HAVE SAME SETTINGS ALREADY
+
+			// } catch (PortInUseException e) {
+			// logText = selectedPort + " is in use. (" + e.toString() + ")";
+			//
+			// System.out.println(logText);
+		} catch (Exception e) {
+			logText = "Failed to open " + selectedPort + "(" + e.toString() + ")";
+			System.out.println(logText);
+			e.printStackTrace();
+		}
+
+	}
+
+	/**
+	 * This method initializes the serial IO stream, after the init is complete
+	 * the method sends an initialize command to the GRID+ controller
+	 * 
+	 * @return successful Boolean value which indicates whether the method was
+	 *         completed successfully
+	 */
+	public void initIOStream() {
+		input = serialPort.getInputStream();
+		output = serialPort.getOutputStream();
+
+		knock();
+		if (!ping())
+			System.err.println("Device did not respond to ping.");
+	}
+
+	private void knock() {
+		for (int i = 0; i < 8; i++) {
+			writeData(new byte[]{(byte) 0xc0});
+		}
+	}
+
+	private boolean ping() {
+		writeData(new byte[]{(byte) 0xc0});
+		return buffer[0] == 0x21;
+	}
+
+	/**
+	 * This method disconnects the serial communication by first closing the
+	 * serialPort and then closing the IOStreams
+	 * 
+	 * 
+	 */
+	public void disconnect() {
+		if (!serialPort.isOpen())
+			return;
+		try {
+			// serialPort.removeEventListener();
+			input.close();
+			output.close();
+			serialPort.closePort();
+			System.out.println("Disconnected.");
+		} catch (IOException e) {
+			logText = "Failed to close " + serialPort.getSystemPortName() + "(" + e.toString() + ")";
+			System.out.println(logText);
+		}
+	}
+
+	// what happens when data is received
+	// pre: serial event is triggered
+	// post: processing on the data it reads
+
+	/**
+	 * This method reads data from the input stream and puts it in a buffer
+	 * after the data is read the method waits 50 msec to make sure a new
+	 * command doesn't follow up to quickly This promotes stability in the
+	 * program.
+	 * @return 
+	 * 
+	 * 
+	 */
+	private byte[] serialRead() throws InterruptedException {
+		try {
+			if (input.available() > 0) {
+				try {
+
+					buffer = (new byte[32]);
+
+					leng = input.read(buffer);
+
+					// Debug.
+					/*
+					 * System.out.println("Length: " + getLeng());
+					 * 
+					 * for (int itera = 0; itera < leng; itera++) {
+					 * System.out.println("byte " + itera + ": " +
+					 * Integer.toHexString(getBuffer(itera) & 0xFF)); }
+					 */
+				} catch (Exception e) {
+					logText = "Failed to read data. (" + e.toString() + ")";
+					System.out.println(logText);
+				}
+			} else {
+				logText = "Failed to read data. No data to read";
+				// System.out.println(logText);
+			}
+
+		} catch (IOException e) {
+			logText = "Failed to read data. (" + e.toString() + ")";
+			System.out.println(logText);
+		}
+		// This prevents commands from being send too soon
+		sleep(50);
+		return buffer;
+	}
+
+	/**
+	 * This method sends a byte array command over the serial communication
+	 * afterwards the method calls the read method
+	 * 
+	 * @param command an array of bytes as a command
+	 */
+	public byte[] writeData(byte[] command) {
+		try {
+			output.write(command);
+			sleep(50);
+			return serialRead();
+		} catch (Exception e) {
+			logText = "Failed to write data. (" + e.toString() + ")";
+			System.out.println(logText);
+			return new byte[32];
+		}
+	}
+
+	/**
+	 *
+	 * @return The second to last byte of the buffer
+	 */
+	public byte getSecondToLast() {
+		if (leng >= 2) {
+			return buffer[leng - 2];
+		} else {
+			return 0;
+		}
+	}
+
+	/**
+	 *
+	 * @return The last byte of the buffer
+	 */
+	public byte getlast() {
+		if (leng >= 2) {
+			return buffer[leng - 1];
+		} else {
+			return 0;
+		}
+	}
+	
+	/**
+	 * @return the portMap
+	 */
+	public HashMap<String, SerialPort> getPortMap() {
+		return portMap;
+	}
+
+	public boolean isConnected() {
+		return serialPort.isOpen();
+	}
 
 }

+ 243 - 308
src/camsucks/model/ComputerModel.java

@@ -1,14 +1,5 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
 package camsucks.model;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.InputStreamReader;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -25,303 +16,247 @@ import java.util.logging.Logger;
  */
 public class ComputerModel {
 
-    // The main components of the Computermodel
-    private Sensor sensor;
-    private GRID grid;
-
-    // The variables used to calculate the percentage to send
-    private double maxCPUTemp;
-    private double maxGPUTemp;
-    private double targetCPUTemp;
-    private double targetGPUTemp;
-    private double targetRPM;
-    // a global minimum percentage, this is used to prevent the controller to constantly turn the fans on and off
-    private int minRPM;
-
-    //Boolean Checks used to know whether to run certain pieces of code
-    private boolean extraPoll;
-    private boolean manual;
-    // private boolean GRIDset;
-    // The percentage to send at the end of the loop.   
-    private int percentageToSend;
-    private int ticks;
-
-    /**
-     *
-     *
-     * All members get initialised here.
-     *
-     * @param selectedPort
-     */
-    public ComputerModel(String selectedPort) {
-        targetRPM = 35;
-        targetCPUTemp = 50;
-        maxCPUTemp = 70;
-        targetGPUTemp = 50;
-        maxGPUTemp = 70;
-        minRPM = 35;
-        extraPoll = true;
-        manual = false;
-        ticks = 0;
-
-        grid = new GRID(selectedPort);
-
-        try {
-            sensor = new Sensor();
-        } catch (Exception ex) {
-            Logger.getLogger(ComputerModel.class.getName()).log(Level.SEVERE, null, ex);
-        }
-    }
-
-    /**
-     *
-     * Currently only the pollCPUPackageTemp method of the sensor object is
-     * called This can change in the future
-     *
-     */
-    public void poll() {
-        //System.out.println("Polling...");
-
-        if (isExtraPoll()) {
-            ticks++;
-            if (!getGrid().isSame() || ticks > 10) {
-                //System.out.println("polling some extra shit ");
-                ticks = 0;
-
-                getGrid().pollVoltage();
-                
-
-                for (int i = 1; i < 7; i++) {
-                    getGrid().pollFanAMP(i);
-                    getGrid().pollFanRPM(i);
-
-                }
-            }
-
-        }
-
-        try {
-            getSensor().pollCPUTemp();
-            getSensor().pollCPUMax();
-            getSensor().pollGPUTemp();
-            getSensor().pollGPUMax();
-            
-            
-        } catch (Exception ex) {
-            System.out.println("Polling Failed");
-        }
-
-    }
-
-    /**
-     *
-     * In this method the percentage to sent is computed. The calculation aims
-     * to act as a proportional controller. A later step could be to add an
-     * integral controller to the calculation to get a better calculated fan
-     * curve
-     *
-     */
-    public void compute() {
-
-        double currentCPUTemp = getSensor().getCPUTemp();
-
-        double CPUerror = (currentCPUTemp - getTargetCPUTemp());
-
-        double CPUkFactor = ((100 - getTargetRPM()) / (getMaxCPUTemp() - getTargetCPUTemp()));
-
-        int tempCPUPercentage = (int) (getTargetRPM() + (CPUkFactor * CPUerror));
-
-        if (tempCPUPercentage < minRPM) {
-            tempCPUPercentage = minRPM;
-        }
-        
-        double currentGPUTemp = getSensor().getGPUTemp();
-
-        double GPUerror = (currentGPUTemp - getTargetGPUTemp());
-
-        double GPUkFactor = ((100 - getTargetRPM()) / (getMaxGPUTemp() - getTargetGPUTemp()));
-
-        int tempGPUPercentage = (int) (getTargetRPM() + (GPUkFactor * GPUerror));
-
-        if (tempGPUPercentage < minRPM) {
-            tempGPUPercentage = minRPM;
-        }
-        
-        if(tempCPUPercentage > tempGPUPercentage){
-            setPercentageToSend(tempCPUPercentage);
-        }   else    {
-            setPercentageToSend(tempGPUPercentage);
-        }
-
-    }
-    
-    public void updateFanSpeed(){
-        getGrid().setFanSpeed(getPercentageToSend());
-    }
-
-    /**
-     * A getter for the Sensor Object to make the methods of the object
-     * available
-     *
-     * @return the sensor
-     */
-    public Sensor getSensor() {
-        return sensor;
-    }
-
-    /**
-     * A getter for the GRID Object to make the methods of the object available
-     *
-     * @return the grid
-     */
-    public GRID getGrid() {
-        return grid;
-    }
-
-    /**
-     * This setter overwrites the old GRID with a new Object with the
-     * selectedport as the COM port to connect to
-     *
-     * @param selectedPort The com port the GRID controller is located at
-     */
-    public void setGrid(String selectedPort) {
-        grid = new GRID(selectedPort);
-    }
-
-    /**
-     * Used to check if the extra polling has to be exicuted
-     *
-     * @return the extraPoll
-     */
-    public boolean isExtraPoll() {
-        return extraPoll;
-    }
-
-    /**
-     * Used to define whether the extra polling must be done
-     *
-     * @param extraPoll the extraPoll to set
-     */
-    public void setExtraPoll(boolean extraPoll) {
-        this.extraPoll = extraPoll;
-    }
-
-    /**
-     *
-     * @return the targetRPM
-     */
-    public double getTargetRPM() {
-        return targetRPM;
-    }
-
-    /**
-     * @param targetRPM the targetRPM to set
-     */
-    public void setTargetRPM(double targetRPM) {
-        this.targetRPM = targetRPM;
-    }
-
-    /**
-     * @return the targetTemp
-     */
-    public double getTargetCPUTemp() {
-        return targetCPUTemp;
-    }
-
-    /**
-     * @param targetTemp the targetTemp to set
-     */
-    public void setTargetCPUTemp(double targetTemp) {
-        this.targetCPUTemp = targetTemp;
-    }
-
-    /**
-     * @return the maxTemp
-     */
-    public double getMaxCPUTemp() {
-        return maxCPUTemp;
-    }
-
-    /**
-     * @param maxTemp the maxTemp to set
-     */
-    public void setMaxCPUTemp(double maxTemp) {
-        this.maxCPUTemp = maxTemp;
-    }
-    /**
-     * @return the targetTemp
-     */
-    public double getTargetGPUTemp() {
-        return targetGPUTemp;
-    }
-
-    /**
-     * @param targetTemp the targetTemp to set
-     */
-    public void setTargetGPUTemp(double targetTemp) {
-        this.targetGPUTemp = targetTemp;
-    }
-
-    /**
-     * @return the maxTemp
-     */
-    public double getMaxGPUTemp() {
-        return maxGPUTemp;
-    }
-
-    /**
-     * @param maxTemp the maxTemp to set
-     */
-    public void setMaxGPUTemp(double maxTemp) {
-        this.maxGPUTemp = maxTemp;
-    }
-
-    /**
-     * A check to see whether the percentage to send is manually set or has to
-     * be calculated
-     *
-     * @return the manual
-     */
-    public boolean isManual() {
-        return manual;
-    }
-
-    /**
-     * @param manual the manual to set
-     */
-    public void setManual(boolean manual) {
-        this.manual = manual;
-    }
-
-    /**
-     * @return the minRPM
-     */
-    public double getMinRPM() {
-        return minRPM;
-    }
-
-    /**
-     *
-     * @param minRPM
-     */
-    public void setMinRPM(int minRPM) {
-        this.minRPM = minRPM;
-    }
-
-    /**
-     * @return the percentageToSend
-     */
-    public int getPercentageToSend() {
-        return percentageToSend;
-    }
-
-    /**
-     * @param percentageToSend the percentageToSend to set
-     */
-    public void setPercentageToSend(int percentageToSend) {
-        this.percentageToSend = percentageToSend;
-    }
-    
-    
-
+	// The main components of the Computermodel
+	private Sensor sensor;
+	private GRID grid;
+
+	// The variables used to calculate the percentage to send
+	private double maxCPUTemp;
+	private double maxGPUTemp;
+	private double targetCPUTemp;
+	private double targetGPUTemp;
+	private double targetRPM;
+	// a global minimum percentage, this is used to prevent the controller to
+	// constantly turn the fans on and off
+	private int minRPM;
+
+	// Boolean Checks used to know whether to run certain pieces of code
+	private boolean manual;
+
+	/**
+	 *
+	 * All members get initialised here.
+	 *
+	 * @param selectedPort
+	 */
+	public ComputerModel(String selectedPort) {
+		targetRPM = 35;
+		targetCPUTemp = 50;
+		maxCPUTemp = 80;
+		targetGPUTemp = 50;
+		maxGPUTemp = 80;
+		minRPM = 20;
+		manual = false;
+
+		grid = new GRID(selectedPort);
+
+		try {
+			sensor = new Sensor();
+		} catch (Exception ex) {
+			Logger.getLogger(ComputerModel.class.getName()).log(Level.SEVERE, null, ex);
+		}
+	}
+
+	/**
+	 *
+	 * Currently only the pollCPUPackageTemp method of the sensor object is
+	 * called This can change in the future
+	 *
+	 */
+	public void poll() {
+		System.out.println("Polling...");
+
+		if (!getGrid().isSame()) {
+			for (int i = 0; i < 6; i++) {
+				getGrid().pollVoltage(i);
+				getGrid().pollFanAMP(i);
+				getGrid().pollFanRPM(i);
+			}
+		}
+
+		try {
+			getSensor().pollCPUTemp();
+			getSensor().pollCPUMax();
+			getSensor().pollGPUTemp();
+			getSensor().pollGPUMax();
+
+		} catch (Exception ex) {
+			System.out.println("Polling Failed");
+			ex.printStackTrace();
+		}
+
+	}
+
+	/**
+	 *
+	 * In this method the percentage to sent is computed. The calculation aims
+	 * to act as a proportional controller. A later step could be to add an
+	 * integral controller to the calculation to get a better calculated fan
+	 * curve
+	 *
+	 */
+	public void compute() {
+		double currentCPUTemp = getSensor().getCPUTemp();
+
+		double CPUerror = (currentCPUTemp - getTargetCPUTemp());
+
+		double CPUkFactor = ((100 - getTargetRPM()) / (getMaxCPUTemp() - getTargetCPUTemp()));
+
+		int tempCPUPercentage = (int) (getTargetRPM() + (CPUkFactor * CPUerror));
+
+		if (tempCPUPercentage < minRPM) {
+			tempCPUPercentage = minRPM;
+		}
+
+		double currentGPUTemp = getSensor().getGPUTemp();
+
+		double GPUerror = (currentGPUTemp - getTargetGPUTemp());
+
+		double GPUkFactor = ((100 - getTargetRPM()) / (getMaxGPUTemp() - getTargetGPUTemp()));
+
+		int tempGPUPercentage = (int) (getTargetRPM() + (GPUkFactor * GPUerror));
+
+		if (tempGPUPercentage < minRPM) {
+			tempGPUPercentage = minRPM;
+		}
+		
+		updateFanSpeed(Math.max(tempCPUPercentage, tempGPUPercentage));
+	}
+
+	public void updateFanSpeed(int percentage) {
+		for (int i = 0; i < 6; i++)
+			getGrid().setFanSpeed(i, percentage);
+	}
+
+	/**
+	 * A getter for the Sensor Object to make the methods of the object
+	 * available
+	 *
+	 * @return the sensor
+	 */
+	public Sensor getSensor() {
+		return sensor;
+	}
+
+	/**
+	 * A getter for the GRID Object to make the methods of the object available
+	 *
+	 * @return the grid
+	 */
+	public GRID getGrid() {
+		return grid;
+	}
+
+	/**
+	 * This setter overwrites the old GRID with a new Object with the
+	 * selectedport as the COM port to connect to
+	 *
+	 * @param selectedPort The com port the GRID controller is located at
+	 */
+	public void setGrid(String selectedPort) {
+		grid = new GRID(selectedPort);
+	}
+
+	/**
+	 *
+	 * @return the targetRPM
+	 */
+	public double getTargetRPM() {
+		return targetRPM;
+	}
+
+	/**
+	 * @param targetRPM the targetRPM to set
+	 */
+	public void setTargetRPM(double targetRPM) {
+		this.targetRPM = targetRPM;
+	}
+
+	/**
+	 * @return the targetTemp
+	 */
+	public double getTargetCPUTemp() {
+		return targetCPUTemp;
+	}
+
+	/**
+	 * @param targetTemp the targetTemp to set
+	 */
+	public void setTargetCPUTemp(double targetTemp) {
+		this.targetCPUTemp = targetTemp;
+	}
+
+	/**
+	 * @return the maxTemp
+	 */
+	public double getMaxCPUTemp() {
+		return maxCPUTemp;
+	}
+
+	/**
+	 * @param maxTemp the maxTemp to set
+	 */
+	public void setMaxCPUTemp(double maxTemp) {
+		this.maxCPUTemp = maxTemp;
+	}
+
+	/**
+	 * @return the targetTemp
+	 */
+	public double getTargetGPUTemp() {
+		return targetGPUTemp;
+	}
+
+	/**
+	 * @param targetTemp the targetTemp to set
+	 */
+	public void setTargetGPUTemp(double targetTemp) {
+		this.targetGPUTemp = targetTemp;
+	}
+
+	/**
+	 * @return the maxTemp
+	 */
+	public double getMaxGPUTemp() {
+		return maxGPUTemp;
+	}
+
+	/**
+	 * @param maxTemp the maxTemp to set
+	 */
+	public void setMaxGPUTemp(double maxTemp) {
+		this.maxGPUTemp = maxTemp;
+	}
+
+	/**
+	 * A check to see whether the percentage to send is manually set or has to
+	 * be calculated
+	 *
+	 * @return the manual
+	 */
+	public boolean isManual() {
+		return manual;
+	}
+
+	/**
+	 * @param manual the manual to set
+	 */
+	public void setManual(boolean manual) {
+		this.manual = manual;
+	}
+
+	/**
+	 * @return the minRPM
+	 */
+	public double getMinRPM() {
+		return minRPM;
+	}
+
+	/**
+	 *
+	 * @param minRPM
+	 */
+	public void setMinRPM(int minRPM) {
+		this.minRPM = minRPM;
+	}
 }

+ 237 - 283
src/camsucks/model/GRID.java

@@ -1,294 +1,248 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
 package camsucks.model;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import javafx.beans.property.SimpleDoubleProperty;
-import javafx.beans.property.SimpleIntegerProperty;
-
 /**
  *
- * This is a model for the GRID controller 
- * This class uses the communicator class to communicate to the GRID+ controller
- * This class contains a few data members that contain data that can be gathered from the GRID+
- * This class has some getters for these members 
- * To update their values they each have poll functions instead of setters which send a command to the GRID and read the response
- * To set the fan speed this class has a setFanSpeed method which sets the voltage of the GRID+ according to a percentage input.
+ * This is a model for the GRID controller This class uses the communicator
+ * class to communicate to the GRID+ controller This class contains a few data
+ * members that contain data that can be gathered from the GRID+ This class has
+ * some getters for these members To update their values they each have poll
+ * functions instead of setters which send a command to the GRID and read the
+ * response To set the fan speed this class has a setFanSpeed method which sets
+ * the voltage of the GRID+ according to a percentage input.
  * 
- * This class also has a boolean check that checks if the voltage command is the same as the previous voltage command, this is to prevent pointless serial communication
- * This check also has a getter to make it usable for other classes 
+ * This class also has a boolean check that checks if the voltage command is the
+ * same as the previous voltage command, this is to prevent pointless serial
+ * communication This check also has a getter to make it usable for other
+ * classes
  * 
  * @author Roel
  */
 public class GRID {
-    
-    private HashMap portMap = new HashMap();
-
-    private double voltage;
-
-    private int[] fanRPM;
-
-    private double[] fanAMP;
-    
-    private double totalWattage;
-
-    private byte[] lastCommand;
-
-    private Communicator communicator;
-    
-    private boolean same;
-
-    /**
-     * This constructor initialises  all members
-     * afterwards it opens a communicator at the selected port 
-     * @param selectedPort the com port to connect to
-     */
-    public GRID(String selectedPort) {
-        
-        totalWattage = 0;
-        lastCommand = new byte[7];
-        lastCommand[5] = 1;
-        lastCommand[6] = 2;
-        voltage = 0;
-        fanAMP = new double[7];
-        fanRPM = new int[7];
-        
-        /*for (int i = 0; i < fanRPM.length; i++) {
-        fanRPM[i] = new SimpleIntegerProperty(0);
-        }
-        
-        for (int i = 0; i < fanAMP.length; i++) {
-        fanAMP[i] = new SimpleDoubleProperty(0);
-        }*/
-        
-        communicator = new Communicator(selectedPort);
-        
-        communicator.searchForPorts();
-        
-        communicator.connect();
-
-        if (communicator.getConnected() == true) {
-           communicator.initIOStream();
-           //System.out.println(Arrays.toString(communicator.getBuffer()));
-          
-           
-        }
-        
-    }
-
-    /**
-     *This method simply runs the disconnect method of the communicator
-     */
-    public void disconnect() {
-
-        if (getCommunicator().getConnected() == true) {
-            getCommunicator().disconnect();
-        }
-
-    }
-
-    /**
-     * @return the voltage
-     */
-    public double getVoltage() {
-        return voltage;
-    }
-
-    /**
-     * @return the fanRPM
-     */
-    public int[] getFanRPM() {
-        return fanRPM;
-    }
-
-    /**
-     * @return the fanAMP
-     */
-    public double[] getFanAMP() {
-        return fanAMP;
-    }
-
-    /**
-     * @param fan the index of the fan
-     * @return the fanRPM of the fan with index fan
-     */
-    public int getFanRPM(int fan) {
-        return fanRPM[fan - 1];
-    }
-
-    /**
-     * @param fan the index of the fan
-     * @return the fanAMP of the fan with index fan
-     */
-    public double getFanAMP(int fan) {
-        return fanAMP[fan - 1];
-    }
-
-    /**
-     * This method polls the Fan Amperage of the fan with index fan
-     * it first send the poll command and reads the byte data from the buffer
-     * this byte data is then converted to a double
-     * @param fan the index of the fan
-     */
-    public void pollFanAMP(int fan) {
-        if (getCommunicator().getConnected() == true) {
-            double tempAMP;
-            // 0x85 = -123
-            byte[] command = {-123, (byte) fan};
-
-            getCommunicator().writeData(command);
-            
-            tempAMP = (double) (((int) getCommunicator().getSecondToLast() & 0xFF) + (((double) (getCommunicator().getlast() & 0xff) / 100)));
-
-            fanAMP[fan - 1] = tempAMP;
-
-        } else {
-            fanAMP[fan - 1] =  0;
-        }
-    }
-
-    /**
-     * This method polls the Fan RPM of the fan with index fan
-     * it first send the poll command and reads the byte data from the buffer
-     * this byte data is then converted to an int
-     * @param fan the index of the fan
-     */
-    public void pollFanRPM(int fan) {
-        if (getCommunicator().getConnected() == true) {
-            // 0x8A = -118            
-
-            byte[] command = {-118, (byte) fan};
-
-            getCommunicator().writeData(command);
-
-            fanRPM[fan - 1] = (((int) (getCommunicator().getSecondToLast() & 0xFF) << 8) | ((getCommunicator().getlast() & 0xFF)));
-
-        } else {
-
-            fanRPM[fan - 1] =  0;
-
-        }
-    }
-
-    /**
-     * This method polls the voltage of all the fans 
-     * it first send the poll command and reads the byte data from the buffer
-     * this byte data is then converted to a double
-     */
-    public void pollVoltage() {
-        if (getCommunicator().getConnected() == true) {
-            // 0x84 = -124
-            byte[] command = {-124, 0x00};
-
-            getCommunicator().writeData(command);
-
-            voltage = (double) (((int) getCommunicator().getSecondToLast() & 0xFF) + (((double) (getCommunicator().getlast() & 0xff) / 100)));
-        } else {
-            voltage = 0;
-        }
-    }
-
-    /**
-     * this method calculates the voltage to set the fans at according to a percentage of the maximum voltage 12V
-     * then it send the command to set that voltage
-     * the voltages between 0 and 4 are not recognised so these are converted to 4V
-     * the comma value of the commands are always rounded to .50 and .0
-     * @param percent
-     */
-    public void setFanSpeed(int percent) {
-
-        if (getCommunicator().getConnected() == true) {
-            int firstByte, lastByte, wantedVoltage;
-            
-            //The voltages between 0 and 4 are not recognised by the grid so any voltage under 4 will still be 4 and from 0 it will be 0
-            if (percent <= 0) {
-                firstByte = 0;
-                lastByte = 0;
-            
-            } else if (percent < 34) {
-                firstByte = 4;
-                lastByte = 0;
-            }else{
-
-                wantedVoltage = (1200 * percent) / 100;
-                firstByte = wantedVoltage / 100;
-                lastByte = (wantedVoltage - (firstByte * 100));
-
-                if (lastByte < 50) {
-                    lastByte = 0x00;
-                } else {
-                    lastByte = 0x50;
-                }
-
-            }
-
-            byte[] command = {0x44, 0x00, -64, 0x00, 0x00, (byte) firstByte, (byte) lastByte};
-            
-            if ((lastCommand[5] != command[5] || lastCommand[6] != command[6])) {
-                getCommunicator().writeData(command);
-                lastCommand = command;
-                setSame(false);
-            } else {
-                setSame(true);
-            }
-            
-            
-
-        }
-
-    }
-
-    /*@Override
-    protected void finalize() throws Throwable {
-    
-    try {
-    disconnect();
-    } finally {
-    super.finalize();
-    }
-    
-    }*/
-    
-    /**
-     * @return the communicator
-     */
-    public Communicator getCommunicator() {
-        return communicator;
-    }
-
-    /**
-     * 
-     * @return A boolean value that is true if the last command is the same as the new
-     */
-    public boolean isSame() {
-        return same;
-    }
-
-    /**
-     * @param same boolean value that is true if the last command is the same as the new
-     */
-    public void setSame(boolean same) {
-        this.same = same;
-    }
-
-    /**
-     * @return the totalWattage
-     */
-    public double getTotalWattage() {
-        totalWattage = 0;
-        for(double tempAMP : fanAMP ){
-            totalWattage = totalWattage + tempAMP*getVoltage();
-            
-        }
-        
-        
-        
-        
-        return totalWattage;
-    }
+
+	private double[] voltage = new double[6];
+
+	private int[] fanRPM = new int[6];
+
+	private double[] fanAMP = new double[6];
+
+	private double totalWattage = 0;
+
+	private byte[] lastCommand = new byte[6];
+
+	private Communicator communicator;
+
+	private boolean same;
+
+	/**
+	 * This constructor initialises all members afterwards it opens a
+	 * communicator at the selected port
+	 * 
+	 * @param selectedPort the com port to connect to
+	 */
+	public GRID(String selectedPort) {
+		lastCommand[4] = 1;
+		lastCommand[5] = 2;
+
+		communicator = new Communicator();
+		communicator.searchForPorts();
+		communicator.connect(selectedPort);
+	}
+
+	/**
+	 * This method simply runs the disconnect method of the communicator
+	 */
+	public void disconnect() {
+		getCommunicator().disconnect();
+	}
+
+	/**
+	 * @return the voltage
+	 */
+	public double[] getVoltage() {
+		return voltage;
+	}
+
+	/**
+	 * @return the fanRPM
+	 */
+	public int[] getFanRPM() {
+		return fanRPM;
+	}
+
+	/**
+	 * @return the fanAMP
+	 */
+	public double[] getFanAMP() {
+		return fanAMP;
+	}
+
+	/**
+	 * @return the voltage
+	 */
+	public double getVoltage(int fan) {
+		return voltage[fan];
+	}
+
+	/**
+	 * @param fan the index of the fan
+	 * @return the fanRPM of the fan with index fan
+	 */
+	public int getRPM(int fan) {
+		return fanRPM[fan];
+	}
+
+	/**
+	 * @param fan the index of the fan
+	 * @return the fanAMP of the fan with index fan
+	 */
+	public double getAMP(int fan) {
+		return fanAMP[fan];
+	}
+
+	/**
+	 * This method polls the Fan Amperage of the fan with index fan it first
+	 * send the poll command and reads the byte data from the buffer this byte
+	 * data is then converted to a double
+	 * 
+	 * @param fan the index of the fan
+	 */
+	public void pollFanAMP(int fan) {
+		if (getCommunicator().isConnected()) {
+			// 0x85 = -123
+			byte[] command = { -123, (byte) (fan + 1) };
+
+			getCommunicator().writeData(command);
+
+			fanAMP[fan] = (double) (((int) getCommunicator().getSecondToLast() & 0xFF) + (((double) (getCommunicator().getlast() & 0xff) / 100)));
+		} else {
+			fanAMP[fan] = 0d;
+		}
+	}
+
+	/**
+	 * This method polls the Fan RPM of the fan with index fan it first send the
+	 * poll command and reads the byte data from the buffer this byte data is
+	 * then converted to an int
+	 * 
+	 * @param fan the index of the fan
+	 */
+	public void pollFanRPM(int fan) {
+		if (getCommunicator().isConnected()) {
+			// 0x8A = -118
+			byte[] command = { -118, (byte) (fan + 1) };
+
+			getCommunicator().writeData(command);
+
+			fanRPM[fan] = (((int) (getCommunicator().getSecondToLast() & 0xFF) << 8) | ((getCommunicator().getlast() & 0xFF)));
+		} else {
+			fanRPM[fan] = 0;
+
+		}
+	}
+
+	/**
+	 * This method polls the voltage of all the fans it first send the poll
+	 * command and reads the byte data from the buffer this byte data is then
+	 * converted to a double
+	 */
+	public void pollVoltage(int fan) {
+		if (getCommunicator().isConnected()) {
+			// 0x84 = -124
+			byte[] command = { -124, (byte) (fan + 1) };
+
+			getCommunicator().writeData(command);
+
+			voltage[fan] = (double) (((int) getCommunicator().getSecondToLast() & 0xFF) + (((double) (getCommunicator().getlast() & 0xff) / 100)));
+		} else {
+			voltage[fan] = 0d;
+		}
+	}
+
+	/**
+	 * this method calculates the voltage to set the fans at according to a
+	 * percentage of the maximum voltage 12V then it send the command to set
+	 * that voltage the voltages between 0 and 4 are not recognised so these are
+	 * converted to 4V the comma value of the commands are always rounded to .50
+	 * and .0
+	 * 
+	 * @param percent
+	 */
+	public void setFanSpeed(int fan, int percent) {
+
+		if (getCommunicator().isConnected()) {
+			int firstByte, lastByte, wantedVoltage;
+
+			// The voltages between 0 and 4 are not recognised by the grid so
+			// any voltage under 4 will still be 4 and from 0 it will be 0
+			if (percent <= 0) {
+				firstByte = 0;
+				lastByte = 0;
+
+			} else if (percent < 34) {
+				firstByte = 4;
+				lastByte = 0;
+			} else {
+
+				wantedVoltage = (1200 * percent) / 100;
+				firstByte = wantedVoltage / 100;
+				lastByte = (wantedVoltage - (firstByte * 100));
+
+				if (lastByte < 50) {
+					lastByte = 0x00;
+				} else {
+					lastByte = 0x50;
+				}
+
+			}
+
+			byte[] command = { 0x44, (byte) (fan + 1), -64, 0x00, 0x00, (byte) firstByte, (byte) lastByte };
+
+			if ((lastCommand[5] != command[5] || lastCommand[6] != command[6])) {
+				getCommunicator().writeData(command);
+				lastCommand = command;
+				setSame(false);
+			} else {
+				setSame(true);
+			}
+
+		}
+
+	}
+
+	/**
+	 * @return the communicator
+	 */
+	public Communicator getCommunicator() {
+		return communicator;
+	}
+
+	/**
+	 * 
+	 * @return A boolean value that is true if the last command is the same as
+	 *         the new
+	 */
+	public boolean isSame() {
+		return same;
+	}
+
+	/**
+	 * @param same boolean value that is true if the last command is the same as
+	 *        the new
+	 */
+	public void setSame(boolean same) {
+		this.same = same;
+	}
+
+	/**
+	 * @return the totalWattage
+	 */
+	public double getTotalWattage() {
+		totalWattage = 0;
+		for (int i = 0; i < fanAMP.length; i++) {
+			totalWattage += getAMP(i) * getVoltage(i);
+		}
+
+		return totalWattage;
+	}
 
 }

+ 4 - 11
src/camsucks/model/Sensor.java

@@ -1,13 +1,5 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
 package camsucks.model;
 
-import java.util.Arrays;
-
-
 /**
  *
  * This class is a model for a collection of sensors
@@ -67,10 +59,11 @@ public class Sensor {
     
     /**
      *  This method polls the value of the CPU Load sensor
+     * @throws NumberFormatException 
      * @throws Exception
      */
-    public void pollCPUMax() throws Exception {
-        cpuMax = Double.parseDouble(jWMI.getWMIValue("Temperature", "CPU Core", "Max"));
+    public void pollCPUMax() throws NumberFormatException, Exception {
+        cpuMax = Double.parseDouble(jWMI.getWMIValue("Temperature", "CPU Package", "Max"));
 
     }
     
@@ -97,7 +90,7 @@ public class Sensor {
      * @throws Exception
      */
     public void pollCPUTemp() throws Exception {
-        cpuPackageTemp = Double.parseDouble(jWMI.getWMIValue("Temperature", "CPU Core"));
+        cpuPackageTemp = Double.parseDouble(jWMI.getWMIValue("Temperature", "CPU Package"));
     }
 
     /**

+ 37 - 21
src/camsucks/model/jWMI.java

@@ -1,12 +1,13 @@
 package camsucks.model;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileWriter;
-import java.io.InputStream;
+import java.io.IOException;
 import java.io.InputStreamReader;
 
+import javax.naming.InvalidNameException;
+
 /**
  * File: jWMI.java Date: 12/21/09 Author: Shaun Henry Copyright Henry Ranch LLC
  * 2009-2010. All rights reserved. http://www.henryranch.net
@@ -141,14 +142,16 @@ public class jWMI {
      *
      * @param envVarName the name of the env var to get
      * @return the value of the env var
+     * @throws IOException 
+     * @throws InvalidNameException 
      * @throws Exception if the given envVarName does not exist
      *
      */
-    private static String getEnvVar(String envVarName) throws Exception {
+    private static String getEnvVar(String envVarName) throws IOException, InvalidNameException {
         String varName = "%" + envVarName + "%";
         String envVarValue = execute(new String[]{"cmd.exe", "/C", "echo " + varName});
         if (envVarValue.equals(varName)) {
-            throw new Exception("Environment variable '" + envVarName + "' does not exist!");
+            throw new InvalidNameException("Environment variable '" + envVarName + "' does not exist!");
         }
         return envVarValue;
     }
@@ -158,10 +161,11 @@ public class jWMI {
      *
      * @param filename the file to write the data to
      * @param data a String ofdata to be written into the file
+     * @throws IOException 
      * @throws Exception if the output file cannot be written
      *
      */
-    private static void writeStrToFile(String filename, String data) throws Exception {
+    private static void writeStrToFile(String filename, String data) throws IOException {
         FileWriter output = new FileWriter(filename);
         output.write(data);
         output.flush();
@@ -174,15 +178,14 @@ public class jWMI {
      *
      * @param SensorType The type of sensor to get a list of
      * @return a comma separated list of the sensors
+     * @throws IOException 
      * @throws Exception if there is a problem obtaining the value
      *
      */
-    public static String getWMISensorList(String SensorType) throws Exception {
+    public static String getWMISensorList(String SensorType) throws IOException {
         String vbScript = getVBScriptList(SensorType);
-        String tmpDirName = getEnvVar("TEMP").trim();
-        String tmpFileName = tmpDirName + File.separator + "jwmi.vbs";
-        writeStrToFile(tmpFileName, vbScript);
-        String output = execute(new String[]{"cmd.exe", "/C", "cscript.exe", tmpFileName});
+        
+        String output = execute(new String[]{"cmd.exe", "/C", "cscript.exe", writeToTempFile(vbScript)});
         //new File(tmpFileName).delete();
 
         return output.trim();
@@ -193,15 +196,13 @@ public class jWMI {
      * @param SensorType the type of the sensor
      * @param name the name of the sensor
      * @return the value of the sensor
+     * @throws IOException 
      * @throws Exception if there is a problem obtaining the value
      *
      */
-    public static String getWMIValue(String SensorType, String name) throws Exception {
+    public static String getWMIValue(String SensorType, String name) throws IOException {
         String vbScript = getVBScriptValue(SensorType, name);
-        String tmpDirName = getEnvVar("TEMP").trim();
-        String tmpFileName = tmpDirName + File.separator + "jwmi.vbs";
-        writeStrToFile(tmpFileName, vbScript);
-        String output = execute(new String[]{"cmd.exe", "/C", "cscript.exe", tmpFileName});
+        String output = execute(new String[]{"cmd.exe", "/C", "cscript.exe", writeToTempFile(vbScript)});
         //new File(tmpFileName).delete();
 
         return output.trim();
@@ -213,15 +214,13 @@ public class jWMI {
      * @param SensorType the type of the sensor
      * @param name the name of the sensor
      * @return the value of the sensor
+     * @throws IOException 
      * @throws Exception if there is a problem obtaining the value
      *
      */
-    public static String getWMIValue(String SensorType, String name, String value) throws Exception {
+    public static String getWMIValue(String SensorType, String name, String value) throws IOException {
         String vbScript = getVBScriptValue(SensorType, name, value);
-        String tmpDirName = getEnvVar("TEMP").trim();
-        String tmpFileName = tmpDirName + File.separator + "jwmi.vbs";
-        writeStrToFile(tmpFileName, vbScript);
-        String output = execute(new String[]{"cmd.exe", "/C", "cscript.exe", tmpFileName});
+        String output = execute(new String[]{"cmd.exe", "/C", "cscript.exe", writeToTempFile(vbScript)});
         //new File(tmpFileName).delete();
 
         return output.trim();
@@ -232,10 +231,11 @@ public class jWMI {
      *
      * @param cmdArray an array of the command line params
      * @return the output as gathered from stdout of the process
+     * @throws IOException 
      * @throws an Exception upon encountering a problem
      *
      */
-    private static String execute(String[] cmdArray) throws Exception {
+    private static String execute(String[] cmdArray) throws IOException {
         Process process = Runtime.getRuntime().exec(cmdArray);
         BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
         String output = "";
@@ -250,6 +250,18 @@ public class jWMI {
         process = null;
         return output.trim();
     }
+    
+    private static String writeToTempFile(String data) throws IOException {
+    	String tmpDirName;
+		try {
+			tmpDirName = getEnvVar("TEMP").trim();
+		} catch (InvalidNameException | IOException e) {
+			tmpDirName = "/temp";
+		}
+        String tmpFileName = tmpDirName + File.separator + "jwmi.vbs";
+        writeStrToFile(tmpFileName, data);
+        return tmpFileName;
+    }
 
     /**
      *
@@ -271,6 +283,10 @@ public class jWMI {
             e.printStackTrace();
         }
     }
+    
+    public static void main(String[] args) {
+    	executeDemoQueries();
+    }
 }
 //WMI class definitions below here: