Page 1 Appendix to the Project Solar Flare: Solar Plant Data Acquisition & Visualization Samuel Caguana Instructor: Dr. Janusz Zalewski CEN 4935 Senior Software Engineering Project Florida Gulf Coast University April 25, 2014 A1- Overview of Previous Project The project taken over is the SolarFlare application maintenance as well as updating several features in the solar.fgcu.edu website. The architecture of the previous project is not changed, as shown in Figure A1. Figure A1: System Architecture The SolarFlare application is located on the Rock server and as of reception of the project, was not operational. The application should run on the server and continuously collect data from solarems.net as shown in Figure A2.
31
Embed
A1- Overview of Previous Projectitech.fgcu.edu/faculty/zalewski/CNT4104/projects/...The architecture of the previous project is not changed, as shown in Figure A1. Figure A1: System
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1
Appendix to the Project Solar Flare: Solar Plant Data Acquisition & Visualization
Samuel Caguana
Instructor: Dr. Janusz Zalewski
CEN 4935 Senior Software Engineering Project
Florida Gulf Coast University
April 25, 2014
A1- Overview of Previous Project
The project taken over is the SolarFlare application maintenance as well as updating
several features in the solar.fgcu.edu website. The architecture of the previous project is not
changed, as shown in Figure A1.
Figure A1: System Architecture
The SolarFlare application is located on the Rock server and as of reception of the
project, was not operational. The application should run on the server and continuously collect
data from solarems.net as shown in Figure A2.
Page 2
Figure A2: SolarFlare Flowchart. [1]
The user shall start the application on the server and it shall automatically connect to
solarems.net. The website shall then check the application credentials; the application shall then
parse the html data and update the database hosted on the database location on the server. The
solar.fgcu.edu website hosts all the data gathered by the SolarFlare application for it to be public.
Solar.fgcu.edu connects to the database located on the Rock server, gathers the data, generates
JSON files and from those files, generates the charts that are displayed on the website. This
process is shown in Figure A3.
Page 3
Figure A3: solar.fgcu.edu Flowchart. [1]
The original application has been developed fully, as described above, but several issues
are preventing it from running. SolarFlare could not successfully access the solarems.net website
to collect data due to not having correct certificates for solarems.net. Another issue was some of
the data collected were not correct. Several values such as the Ambient Temperature and the
Energy Total were not read correctly as it was in the solarems.net website.
Additionally, the solar.fgcu.edu website had an issue where it would take a several
minutes to load the graph pages. The website page would be blocked while it refreshed and
loaded the data to be displayed.
Page 4
A2- New Objectives
This maintenance of the SolarFlare application and the solar.fgcu.edu website has to
include the repair of the connection between SolarFlare and solarems.net, correct the data
acquisition of the invalid values from solarems.net as well as increase efficiency of
solar.fgcu.edu. New features shall be attempted to be added to the current project during the
maintenance without hindering the quality and functionality of the current state of the project.
New objectives include making SolarFlare operational and maintaining it functional,
adding and fixing linked content on solar.fgcu.edu and also making the website more efficient.
The SolarFlare application shall be running continuously on the server as it was originally
intended to.
Several links to new publications about the FGCU’s solar field need to be added as well
as a feature to allow users who have accounts on solarems.net to be able to login via
solar.fgcu.edu. More user control over displayed data shall be a new feature added to the
website. This feature shall also improve on the efficiency of the website, as shown in Figure A4,
by making it load faster due to information pulling from the database being at a minimum.
Figure A4: Website- solar.fgcu.edu
Page 5
A3- Implementation
The SolarFlare applications class diagram is shown in Figure A5. This shows the
connection of each class and the operation, as a whole, of the application. The application is a
web crawler, HTML parser as well as a database manager. As shown in the figure below, the
HTMLNavigator class is the web crawler section of the application. This section is responsible
for connecting to solarems.net, navigating the site and retrieving data. The HTMLParser class is
in charge of parsing through the data retrieved and converting it to text. The DBManager class is
in charge of taking the text parsed and updating the database with the relevant information.
Figure A5: SolarFlare Class Diagram. [1]
In maintaining the SolarFlare application, the issues discovered were that the application
did not connect to solarems.net and some of the data being gathered were not correct. The
solarems website login screen is shown in Figure A6.
Page 6
Figure A6: Website- solarems.net
The application was giving the errors that it could not access solarems.net. These errors
were due to SolarFlare not having the correct secure sockets layer (SSL) certificates for the
website. The correct certificates were retrieved by an open source project InstallCert [2]
developed by Sun Microsystems and the application could successfully access solarems.net.
InstallCert is an open source java project to retrieve SSL certificates securely from a website an
application accesses and stores them locally in the Java JDK security folders for the application
to access when running. The InstallCert.java program is shown in Section A7.
Page 7
Figure A7: Incorrect Data Gathered
Figure A7 shows the issue of incorrect data being gathered. The “Ambient …” column
shows the ambient temperature of the area around the solar panels in degrees Celsius, but as
shown, these temperatures are reaching 600 degrees Celsius, which is highly incorrect data.
Also, the “AC Energy” column values were also off compared to the represented values in
solarems.net. These issues were caused by parsing errors in the SolarFlare application code. The
code section where the errors were created is shown in Figure A8.
<script language="JavaScript"> function checkTextboxes() { var userhour = document.getElementById('userhour').value; var userminute = document.getElementById('userminute').value; var userday = document.getElementById('userday').value; var usermonth = document.getElementById('usermonth').value; var useryear = document.getElementById('useryear').value; var userrecord = document.getElementById('userrecord').value; if(!userhour.match(/\S/) || !userminute.match(/\S/) || !userday.match(/\S/) || !usermonth.match(/\S/) || !useryear.match(/\S/) || !userrecord.match(/\S/) || isNaN(userhour) || isNaN(userminute) || isNaN(userday) || isNaN(usermonth) || isNaN(useryear) || isNaN(userrecord)) {
alert ("Value's left blank or incorrect input.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
alert ("Make correct day input for your current month.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
} } else{
Page 26
alert ("Make correct day input for your current month.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
} } else{
alert ("Hour needs to be between 0 and 23 inclusive.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
} } else{
alert ("Month needs to be between 1 and 12 inclusive.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
} } else{
alert ("Year needs to be 2010 or after.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
} } else{
alert ("Minute needs to either be 00, 15, 30 or 45.\nReverting to default start date."); document.location.href = "environmental.php?usertime=18%3A45&userday=1&usermonth=4&useryear=2010&userrecord=24#";
} } } </script>
Page 27
A9- InstallCert.java
/* * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. * */ /** * Use: * java InstallCert hostname */ import javax.net.ssl.*; import java.io.*; import java.security.KeyStore; import java.security.MessageDigest; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; /** * Class used to add the server's certificate to the KeyStore * with your trusted certificates. */ public class InstallCert { public static void main(String[] args) throws Exception { String host; int port; char[] passphrase; if ((args.length == 1) || (args.length == 2)) { String[] c = args[0].split(":"); host = c[0]; port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); String p = (args.length == 1) ? "changeit" : args[1]; passphrase = p.toCharArray();
Page 28
} else { System.out.println("Usage: java InstallCert <host>[:port] [passphrase]"); return; } File file = new File("jssecacerts"); if (file.isFile() == false) { char SEP = File.separatorChar; File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security"); file = new File(dir, "jssecacerts"); if (file.isFile() == false) { file = new File(dir, "cacerts"); } } System.out.println("Loading KeyStore " + file + "..."); InputStream in = new FileInputStream(file); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(in, passphrase); in.close(); SSLContext context = SSLContext.getInstance("TLS"); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0]; SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); context.init(null, new TrustManager[]{tm}, null); SSLSocketFactory factory = context.getSocketFactory(); System.out.println("Opening connection to " + host + ":" + port + "..."); SSLSocket socket = (SSLSocket) factory.createSocket(host, port); socket.setSoTimeout(10000); try { System.out.println("Starting SSL handshake..."); socket.startHandshake(); socket.close(); System.out.println(); System.out.println("No errors, certificate is already trusted"); } catch (SSLException e) { System.out.println(); e.printStackTrace(System.out);
Page 29
} X509Certificate[] chain = tm.chain; if (chain == null) { System.out.println("Could not obtain server certificate chain"); return; } BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println(); System.out.println("Server sent " + chain.length + " certificate(s):"); System.out.println(); MessageDigest sha1 = MessageDigest.getInstance("SHA1"); MessageDigest md5 = MessageDigest.getInstance("MD5"); for (int i = 0; i < chain.length; i++) { X509Certificate cert = chain[i]; System.out.println (" " + (i + 1) + " Subject " + cert.getSubjectDN()); System.out.println(" Issuer " + cert.getIssuerDN()); sha1.update(cert.getEncoded()); System.out.println(" sha1 " + toHexString(sha1.digest())); md5.update(cert.getEncoded()); System.out.println(" md5 " + toHexString(md5.digest())); System.out.println(); } System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); String line = reader.readLine().trim(); int k; try { k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; } catch (NumberFormatException e) { System.out.println("KeyStore not changed"); return; } X509Certificate cert = chain[k]; String alias = host + "-" + (k + 1); ks.setCertificateEntry(alias, cert); OutputStream out = new FileOutputStream("jssecacerts"); ks.store(out, passphrase);
Page 30
out.close(); System.out.println(); System.out.println(cert); System.out.println(); System.out.println ("Added certificate to keystore 'jssecacerts' using alias '" + alias + "'"); } private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); private static String toHexString(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 3); for (int b : bytes) { b &= 0xff; sb.append(HEXDIGITS[b >> 4]); sb.append(HEXDIGITS[b & 15]); sb.append(' '); } return sb.toString(); } private static class SavingTrustManager implements X509TrustManager { private final X509TrustManager tm; private X509Certificate[] chain; SavingTrustManager(X509TrustManager tm) { this.tm = tm; } public X509Certificate[] getAcceptedIssuers() { throw new UnsupportedOperationException(); } public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { throw new UnsupportedOperationException(); } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { this.chain = chain; tm.checkServerTrusted(chain, authType);